From 6460c9d5d1cdd6e48752c0de4dbdb7d4e31742aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 11:49:11 +0200
Subject: [PATCH 01/19] Move the AMC manager classes inside gem::hardware

---
 doc/examples/xml/gem904daq04.xml              |   4 +-
 gemhardware/managers/CMakeLists.txt           |   4 +-
 gemhardware/managers/interface/AMCManager.h   | 119 +++++++++++++++++
 .../managers/interface/AMCManagerWeb.h        |  47 +++++++
 .../managers/interface/amc/AMCManager.h       | 120 ------------------
 .../managers/interface/amc/AMCManagerWeb.h    |  49 -------
 .../managers/src/{amc => }/AMCManager.cpp     |  63 ++++-----
 .../managers/src/{amc => }/AMCManagerWeb.cpp  |  30 ++---
 8 files changed, 213 insertions(+), 223 deletions(-)
 create mode 100644 gemhardware/managers/interface/AMCManager.h
 create mode 100644 gemhardware/managers/interface/AMCManagerWeb.h
 delete mode 100644 gemhardware/managers/interface/amc/AMCManager.h
 delete mode 100644 gemhardware/managers/interface/amc/AMCManagerWeb.h
 rename gemhardware/managers/src/{amc => }/AMCManager.cpp (92%)
 rename gemhardware/managers/src/{amc => }/AMCManagerWeb.cpp (65%)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index ad84030a..82030f1d 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -105,8 +105,8 @@
       </properties>
     </xc:Application>
 
-    <xc:Application class="gem::hardware::amc::AMCManager" id="30" instance="0" network="local">
-      <properties xmlns="urn:xdaq-application:gem::hardware::amc::AMCManager" xsi:type="soapenc:Struct">
+    <xc:Application class="gem::hardware::AMCManager" id="30" instance="0" network="local">
+      <properties xmlns="urn:xdaq-application:gem::hardware::AMCManager" xsi:type="soapenc:Struct">
         <DisableMonitoring xsi:type="xsd:boolean">true</DisableMonitoring>
         <AMCSlots xsi:type="xsd:string">2</AMCSlots>
         <AllAMCsInfo xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[12]">
diff --git a/gemhardware/managers/CMakeLists.txt b/gemhardware/managers/CMakeLists.txt
index 5452a468..14521e0f 100644
--- a/gemhardware/managers/CMakeLists.txt
+++ b/gemhardware/managers/CMakeLists.txt
@@ -2,8 +2,8 @@ cmsgemos_add_module(
     managers
     SOURCES
     version.cpp
-    amc/AMCManager.cpp
-    amc/AMCManagerWeb.cpp
+    AMCManager.cpp
+    AMCManagerWeb.cpp
     amc13/AMC13Manager.cpp
     amc13/AMC13ManagerWeb.cpp
     amc13/AMC13Readout.cpp
diff --git a/gemhardware/managers/interface/AMCManager.h b/gemhardware/managers/interface/AMCManager.h
new file mode 100644
index 00000000..8709353a
--- /dev/null
+++ b/gemhardware/managers/interface/AMCManager.h
@@ -0,0 +1,119 @@
+/// @file AMCManager.h
+
+#ifndef GEM_HARDWARE_AMCMANAGER_H
+#define GEM_HARDWARE_AMCMANAGER_H
+
+#include "gem/base/GEMFSMApplication.h"
+#include "gem/utils/soap/GEMSOAPToolBox.h"
+
+#include <array>
+
+namespace gem {
+namespace hardware {
+
+    class AMCManagerWeb;
+    namespace amc {
+        class HwGenericAMC;
+    }
+
+    using amc_shared_ptr = std::shared_ptr<gem::hardware::amc::HwGenericAMC>;
+    using is_toolbox_ptr = std::shared_ptr<gem::base::utils::GEMInfoSpaceToolBox>;
+
+    class AMCManager : public gem::base::GEMFSMApplication {
+
+        friend class AMCManagerWeb;
+
+    public:
+        XDAQ_INSTANTIATOR();
+
+        AMCManager(xdaq::ApplicationStub* s);
+
+        virtual ~AMCManager();
+
+    protected:
+        /* virtual void init() override; */
+        void init();
+
+        virtual void actionPerformed(xdata::Event& event) override;
+
+        // state transitions FIXME: remove exception specifiers
+        virtual void initializeAction() override;
+        virtual void configureAction() override;
+        virtual void startAction() override;
+        virtual void pauseAction() override;
+        virtual void resumeAction() override;
+        virtual void stopAction() override;
+        virtual void haltAction() override;
+        virtual void resetAction() override;
+        // virtual void noAction()         override;
+
+        void failAction(toolbox::Event::Reference e);
+
+        virtual void resetAction(toolbox::Event::Reference e) override;
+
+    private:
+        uint16_t m_amcEnableMask;
+
+        toolbox::task::WorkLoop* p_amc_wl; ///< paralelize the calls to different AMCs
+        toolbox::BSem m_amc_wl_semaphore[MAX_AMCS_PER_CRATE]; ///< do we need a semaphore for the workloop or each of them?
+
+        class AMCInfo {
+
+        public:
+            AMCInfo();
+            void registerFields(xdata::Bag<AMCManager::AMCInfo>* bag);
+
+            // monitoring information
+            xdata::Boolean present; ///< FIXME BAD USAGE
+            xdata::Integer crateID; ///< Specifies the crate to which the OptoHybrid is connected
+            xdata::Integer slotID; ///< Specifies the AMC slot to which the OptoHybrid is connected
+
+            // list of GTX links to enable in the DAQ
+            xdata::String gtxLinkEnableList;
+            xdata::UnsignedInteger32 gtxLinkEnableMask;
+
+            // registers to set
+            xdata::Integer sbitSource;
+            xdata::Boolean enableZS;
+
+            inline std::string toString()
+            {
+                std::stringstream os;
+                os << "present:" << present.toString() << std::endl
+                   << "crateID:" << crateID.toString() << std::endl
+                   << "slotID:" << slotID.toString() << std::endl
+
+                   << "gtxLinkEnableList:" << gtxLinkEnableList.toString() << std::endl
+                   << "gtxLinkEnableMask:" << std::hex << gtxLinkEnableMask.value_ << std::dec << std::endl
+
+                   << "sbitSource:0x" << std::hex << sbitSource.value_ << std::dec << std::endl
+                   << "enableZS:0x" << std::hex << enableZS.value_ << std::dec << std::endl
+                   << std::endl;
+                return os.str();
+            };
+        };
+
+        mutable gem::utils::Lock m_deviceLock; ///< [MAX_AMCS_PER_CRATE];
+
+        std::array<amc_shared_ptr, MAX_AMCS_PER_CRATE> m_amcs; ///< HwGLIB pointers to be managed
+        std::array<is_toolbox_ptr, MAX_AMCS_PER_CRATE> is_amcs; ///< AMC InfoSpace pointers to be managed
+
+        xdata::Vector<xdata::Bag<AMCInfo>> m_amcInfo; ///< [MAX_AMCS_PER_CRATE];
+        xdata::String m_amcSlots; ///<
+        xdata::String m_connectionFile; ///<
+        xdata::Boolean m_doPhaseShift; ///< Whether or not to do a phase shifting procedure during configuration
+        xdata::Boolean m_bc0LockPhaseShift; ///< Use BC0 to find the best phase during the phase shifting procedure
+        xdata::Boolean m_relockPhase; ///< Relock the phase during phase shifting
+
+        uint32_t m_lastLatency; ///< Special variable for latency scan mode
+        uint32_t m_lastVT1, m_lastVT2; ///< Special variable for threshold scan mode
+
+        xoap::MessageReference setRunTypeInterCalib(xoap::MessageReference msg);
+        //xoap::MessageReference calibParamPrint(xoap::MessageReference msg);
+        xoap::MessageReference updateRunParamCalib(xoap::MessageReference msg);
+
+    }; // class AMCManager
+} // namespace gem::hardware
+} // namespace gem
+
+#endif // GEM_HARDWARE_AMCMANAGER_H
diff --git a/gemhardware/managers/interface/AMCManagerWeb.h b/gemhardware/managers/interface/AMCManagerWeb.h
new file mode 100644
index 00000000..3b4ad75f
--- /dev/null
+++ b/gemhardware/managers/interface/AMCManagerWeb.h
@@ -0,0 +1,47 @@
+/// @file AMCManagerWeb.h
+
+#ifndef GEM_HARDWARE_AMCMANAGERWEB_H
+#define GEM_HARDWARE_AMCMANAGERWEB_H
+
+#include "gem/base/GEMWebApplication.h"
+
+namespace gem {
+namespace hardware {
+
+    class AMCManager;
+
+    class AMCManagerWeb : public gem::base::GEMWebApplication {
+        friend class AMCManager;
+
+    public:
+        AMCManagerWeb(AMCManager* amcApp);
+
+        virtual ~AMCManagerWeb();
+
+    protected:
+        virtual void webDefault(xgi::Input* in, xgi::Output* out);
+
+        virtual void monitorPage(xgi::Input* in, xgi::Output* out);
+
+        virtual void expertPage(xgi::Input* in, xgi::Output* out);
+
+        virtual void applicationPage(xgi::Input* in, xgi::Output* out);
+
+        virtual void jsonUpdate(xgi::Input* in, xgi::Output* out);
+
+        /* void buildCardSummaryTable(xgi::Input* in, xgi::Output* out); */
+
+        /* void cardPage(xgi::Input* in, xgi::Output* out); */
+
+        void registerDumpPage(xgi::Input* in, xgi::Output* out);
+
+    private:
+        size_t activeCard;
+
+        //AMCManagerWeb(AMCManagerWeb const&);
+    };
+
+} // namespace gem::hardware
+} // namespace gem
+
+#endif // GEM_HARDWARE_AMCMANAGERWEB_H
diff --git a/gemhardware/managers/interface/amc/AMCManager.h b/gemhardware/managers/interface/amc/AMCManager.h
deleted file mode 100644
index fccd4e16..00000000
--- a/gemhardware/managers/interface/amc/AMCManager.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/// @file AMCManager.h
-
-#ifndef GEM_HARDWARE_AMC_AMCMANAGER_H
-#define GEM_HARDWARE_AMC_AMCMANAGER_H
-
-#include <array>
-
-#include "gem/base/GEMFSMApplication.h"
-
-#include "gem/utils/soap/GEMSOAPToolBox.h"
-
-namespace gem {
-namespace hardware {
-    namespace amc {
-
-        class AMCManagerWeb;
-        class HwGenericAMC;
-
-        using amc_shared_ptr = std::shared_ptr<gem::hardware::amc::HwGenericAMC>;
-        using is_toolbox_ptr = std::shared_ptr<gem::base::utils::GEMInfoSpaceToolBox>;
-
-        class AMCManager : public gem::base::GEMFSMApplication {
-
-            friend class AMCManagerWeb;
-
-        public:
-            XDAQ_INSTANTIATOR();
-
-            AMCManager(xdaq::ApplicationStub* s);
-
-            virtual ~AMCManager();
-
-        protected:
-            /* virtual void init() override; */
-            void init();
-
-            virtual void actionPerformed(xdata::Event& event) override;
-
-            // state transitions FIXME: remove exception specifiers
-            virtual void initializeAction() override;
-            virtual void configureAction() override;
-            virtual void startAction() override;
-            virtual void pauseAction() override;
-            virtual void resumeAction() override;
-            virtual void stopAction() override;
-            virtual void haltAction() override;
-            virtual void resetAction() override;
-            // virtual void noAction()         override;
-
-            void failAction(toolbox::Event::Reference e);
-
-            virtual void resetAction(toolbox::Event::Reference e) override;
-
-        private:
-            uint16_t m_amcEnableMask;
-
-            toolbox::task::WorkLoop* p_amc_wl; ///< paralelize the calls to different AMCs
-            toolbox::BSem m_amc_wl_semaphore[MAX_AMCS_PER_CRATE]; ///< do we need a semaphore for the workloop or each of them?
-
-            class AMCInfo {
-
-            public:
-                AMCInfo();
-                void registerFields(xdata::Bag<AMCManager::AMCInfo>* bag);
-
-                // monitoring information
-                xdata::Boolean present; ///< FIXME BAD USAGE
-                xdata::Integer crateID; ///< Specifies the crate to which the OptoHybrid is connected
-                xdata::Integer slotID; ///< Specifies the AMC slot to which the OptoHybrid is connected
-
-                // list of GTX links to enable in the DAQ
-                xdata::String gtxLinkEnableList;
-                xdata::UnsignedInteger32 gtxLinkEnableMask;
-
-                // registers to set
-                xdata::Integer sbitSource;
-                xdata::Boolean enableZS;
-
-                inline std::string toString()
-                {
-                    std::stringstream os;
-                    os << "present:" << present.toString() << std::endl
-                       << "crateID:" << crateID.toString() << std::endl
-                       << "slotID:" << slotID.toString() << std::endl
-
-                       << "gtxLinkEnableList:" << gtxLinkEnableList.toString() << std::endl
-                       << "gtxLinkEnableMask:" << std::hex << gtxLinkEnableMask.value_ << std::dec << std::endl
-
-                       << "sbitSource:0x" << std::hex << sbitSource.value_ << std::dec << std::endl
-                       << "enableZS:0x" << std::hex << enableZS.value_ << std::dec << std::endl
-                       << std::endl;
-                    return os.str();
-                };
-            };
-
-            mutable gem::utils::Lock m_deviceLock; ///< [MAX_AMCS_PER_CRATE];
-
-            std::array<amc_shared_ptr, MAX_AMCS_PER_CRATE> m_amcs; ///< HwGLIB pointers to be managed
-            std::array<is_toolbox_ptr, MAX_AMCS_PER_CRATE> is_amcs; ///< AMC InfoSpace pointers to be managed
-
-            xdata::Vector<xdata::Bag<AMCInfo>> m_amcInfo; ///< [MAX_AMCS_PER_CRATE];
-            xdata::String m_amcSlots; ///<
-            xdata::String m_connectionFile; ///<
-            xdata::Boolean m_doPhaseShift; ///< Whether or not to do a phase shifting procedure during configuration
-            xdata::Boolean m_bc0LockPhaseShift; ///< Use BC0 to find the best phase during the phase shifting procedure
-            xdata::Boolean m_relockPhase; ///< Relock the phase during phase shifting
-
-            uint32_t m_lastLatency; ///< Special variable for latency scan mode
-            uint32_t m_lastVT1, m_lastVT2; ///< Special variable for threshold scan mode
-
-            xoap::MessageReference setRunTypeInterCalib(xoap::MessageReference msg);
-            //xoap::MessageReference calibParamPrint(xoap::MessageReference msg);
-            xoap::MessageReference updateRunParamCalib(xoap::MessageReference msg);
-
-        }; // class AMCManager
-    } // namespace gem::hardware::amc
-} // namespace gem::hardware
-} // namespace gem
-
-#endif // GEM_HARDWARE_AMC_AMCMANAGER_H
diff --git a/gemhardware/managers/interface/amc/AMCManagerWeb.h b/gemhardware/managers/interface/amc/AMCManagerWeb.h
deleted file mode 100644
index 00a28458..00000000
--- a/gemhardware/managers/interface/amc/AMCManagerWeb.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/// @file AMCManagerWeb.h
-
-#ifndef GEM_HARDWARE_AMC_AMCMANAGERWEB_H
-#define GEM_HARDWARE_AMC_AMCMANAGERWEB_H
-
-#include "gem/base/GEMWebApplication.h"
-
-namespace gem {
-namespace hardware {
-    namespace amc {
-
-        class AMCManager;
-
-        class AMCManagerWeb : public gem::base::GEMWebApplication {
-            friend class AMCManager;
-
-        public:
-            AMCManagerWeb(AMCManager* amcApp);
-
-            virtual ~AMCManagerWeb();
-
-        protected:
-            virtual void webDefault(xgi::Input* in, xgi::Output* out);
-
-            virtual void monitorPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void expertPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void applicationPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void jsonUpdate(xgi::Input* in, xgi::Output* out);
-
-            /* void buildCardSummaryTable(xgi::Input* in, xgi::Output* out); */
-
-            /* void cardPage(xgi::Input* in, xgi::Output* out); */
-
-            void registerDumpPage(xgi::Input* in, xgi::Output* out);
-
-        private:
-            size_t activeCard;
-
-            //AMCManagerWeb(AMCManagerWeb const&);
-        };
-
-    } // namespace gem::amc
-} // namespace gem::hardware
-} // namespace gem
-
-#endif // GEM_HARDWARE_AMC_AMCMANAGERWEB_H
diff --git a/gemhardware/managers/src/amc/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
similarity index 92%
rename from gemhardware/managers/src/amc/AMCManager.cpp
rename to gemhardware/managers/src/AMCManager.cpp
index 63281091..0ad084ec 100644
--- a/gemhardware/managers/src/amc/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -1,17 +1,10 @@
-/// class: AMCManager
-/// description: Manager application for AMC cards
-///              structure borrowed from TCDS core, with nods to HCAL and EMU code
-/// author: J. Sturdy
-/// date:
+/// @file AMCManager.cpp
 
-#include "gem/hardware/devices/amc/HwGenericAMC.h"
-
-#include "gem/hardware/managers/amc/AMCManager.h"
-
-#include "gem/hardware/managers/amc/AMCManagerWeb.h"
+#include "gem/hardware/managers/AMCManager.h"
 
+#include "gem/hardware/devices/amc/HwGenericAMC.h"
+#include "gem/hardware/managers/AMCManagerWeb.h"
 #include "gem/hardware/managers/exception/Exception.h"
-
 #include "gem/hardware/utils/GEMCrateUtils.h"
 
 #include "xoap/AttachmentPart.h"
@@ -25,9 +18,9 @@
 
 #include <iterator>
 
-XDAQ_INSTANTIATOR_IMPL(gem::hardware::amc::AMCManager);
+XDAQ_INSTANTIATOR_IMPL(gem::hardware::AMCManager);
 
-gem::hardware::amc::AMCManager::AMCInfo::AMCInfo()
+gem::hardware::AMCManager::AMCInfo::AMCInfo()
 {
     present = false;
     crateID = -1;
@@ -36,7 +29,7 @@ gem::hardware::amc::AMCManager::AMCInfo::AMCInfo()
     enableZS = true;
 }
 
-void gem::hardware::amc::AMCManager::AMCInfo::registerFields(xdata::Bag<gem::hardware::amc::AMCManager::AMCInfo>* bag)
+void gem::hardware::AMCManager::AMCInfo::registerFields(xdata::Bag<gem::hardware::AMCManager::AMCInfo>* bag)
 {
     bag->addField("crateID", &crateID);
     bag->addField("slot", &slotID);
@@ -45,7 +38,7 @@ void gem::hardware::amc::AMCManager::AMCInfo::registerFields(xdata::Bag<gem::har
     bag->addField("enableZS", &enableZS);
 }
 
-gem::hardware::amc::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
+gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
     : gem::base::GEMFSMApplication(stub)
     , m_amcEnableMask(0)
     , m_doPhaseShift(false)
@@ -76,28 +69,28 @@ gem::hardware::amc::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
 
     // initialize the AMC application objects
     CMSGEMOS_DEBUG("AMCManager::Connecting to the AMCManagerWeb interface");
-    p_gemWebInterface = new gem::hardware::amc::AMCManagerWeb(this);
+    p_gemWebInterface = new gem::hardware::AMCManagerWeb(this);
     CMSGEMOS_DEBUG("AMCManager::done");
 
     // set up the info hwCfgInfoSpace
     xoap::bind<gem::base::GEMApplication>(this, &gem::base::GEMApplication::calibParamRetrieve, "calibParamRetrieve", XDAQ_NS_URI);
 
-    //xoap::bind(this, &gem::hardware::amc::AMCManager::calibParamPrint, "calibParamPrint", XDAQ_NS_URI);
-    xoap::bind(this, &gem::hardware::amc::AMCManager::setRunTypeInterCalib, "setRunTypeInterCalib", XDAQ_NS_URI);
-    xoap::bind(this, &gem::hardware::amc::AMCManager::updateRunParamCalib, "updateRunParamCalib", XDAQ_NS_URI);
+    //xoap::bind(this, &gem::hardware::AMCManager::calibParamPrint, "calibParamPrint", XDAQ_NS_URI);
+    xoap::bind(this, &gem::hardware::AMCManager::setRunTypeInterCalib, "setRunTypeInterCalib", XDAQ_NS_URI);
+    xoap::bind(this, &gem::hardware::AMCManager::updateRunParamCalib, "updateRunParamCalib", XDAQ_NS_URI);
 
     init();
 
     // getApplicationDescriptor()->setAttribute("icon","/gemdaq/gemhardware/images/amc/AMCManager.png");
 }
 
-gem::hardware::amc::AMCManager::~AMCManager()
+gem::hardware::AMCManager::~AMCManager()
 {
     // memory management, maybe not necessary here?
 }
 
 // This is the callback used for handling xdata:Event objects
-void gem::hardware::amc::AMCManager::actionPerformed(xdata::Event& event)
+void gem::hardware::AMCManager::actionPerformed(xdata::Event& event)
 {
     if (event.type() == "setDefaultValues" || event.type() == "urn:xdaq-event:setDefaultValues") {
         CMSGEMOS_DEBUG("AMCManager::actionPerformed() setDefaultValues"
@@ -121,13 +114,13 @@ void gem::hardware::amc::AMCManager::actionPerformed(xdata::Event& event)
     gem::base::GEMApplication::actionPerformed(event);
 }
 
-void gem::hardware::amc::AMCManager::init()
+void gem::hardware::AMCManager::init()
 {
     // anything needed here?
 }
 
 // state transitions
-void gem::hardware::amc::AMCManager::initializeAction()
+void gem::hardware::AMCManager::initializeAction()
 {
     CMSGEMOS_DEBUG("AMCManager::initializeAction begin");
     //
@@ -178,7 +171,7 @@ void gem::hardware::amc::AMCManager::initializeAction()
     CMSGEMOS_INFO("AMCManager::initializeAction end");
 }
 
-void gem::hardware::amc::AMCManager::configureAction()
+void gem::hardware::AMCManager::configureAction()
 {
     CMSGEMOS_DEBUG("AMCManager::configureAction");
 
@@ -259,7 +252,7 @@ void gem::hardware::amc::AMCManager::configureAction()
     CMSGEMOS_INFO("AMCManager::configureAction end");
 }
 
-void gem::hardware::amc::AMCManager::startAction()
+void gem::hardware::AMCManager::startAction()
 {
 
     if (m_scanInfo.bag.scanType.value_ == 2) {
@@ -308,7 +301,7 @@ void gem::hardware::amc::AMCManager::startAction()
     CMSGEMOS_INFO("AMCManager::startAction end");
 }
 
-void gem::hardware::amc::AMCManager::pauseAction()
+void gem::hardware::AMCManager::pauseAction()
 {
     // what is required for pausing the AMC?
     // FIXME make me more streamlined
@@ -379,13 +372,13 @@ void gem::hardware::amc::AMCManager::pauseAction()
     CMSGEMOS_INFO("AMCManager::pauseAction end");
 }
 
-void gem::hardware::amc::AMCManager::resumeAction()
+void gem::hardware::AMCManager::resumeAction()
 {
     // what is required for resuming the AMC?
     CMSGEMOS_INFO("AMCManager::resumeAction end");
 }
 
-void gem::hardware::amc::AMCManager::stopAction()
+void gem::hardware::AMCManager::stopAction()
 {
     CMSGEMOS_INFO("AMCManager::stopAction begin");
     // FIXME make me more streamlined
@@ -410,7 +403,7 @@ void gem::hardware::amc::AMCManager::stopAction()
     CMSGEMOS_INFO("AMCManager::stopAction end");
 }
 
-void gem::hardware::amc::AMCManager::haltAction()
+void gem::hardware::AMCManager::haltAction()
 {
     // what is required for halting the AMC?
     CMSGEMOS_DEBUG("AMCManager::resetAction begin");
@@ -433,7 +426,7 @@ void gem::hardware::amc::AMCManager::haltAction()
     CMSGEMOS_INFO("AMCManager::haltAction end");
 }
 
-void gem::hardware::amc::AMCManager::resetAction()
+void gem::hardware::AMCManager::resetAction()
 {
     // what is required for resetting the AMC?
     // unregister listeners and items in info spaces
@@ -475,20 +468,20 @@ void gem::hardware::amc::AMCManager::resetAction()
 }
 
 /*
-  void gem::hardware::amc::AMCManager::noAction()
+  void gem::hardware::AMCManager::noAction()
   {
   }
 */
 
-void gem::hardware::amc::AMCManager::failAction(toolbox::Event::Reference e)
+void gem::hardware::AMCManager::failAction(toolbox::Event::Reference e)
 {
 }
 
-void gem::hardware::amc::AMCManager::resetAction(toolbox::Event::Reference e)
+void gem::hardware::AMCManager::resetAction(toolbox::Event::Reference e)
 {
 }
 
-xoap::MessageReference gem::hardware::amc::AMCManager::setRunTypeInterCalib(xoap::MessageReference msg)
+xoap::MessageReference gem::hardware::AMCManager::setRunTypeInterCalib(xoap::MessageReference msg)
 {
     const std::string commandName = "setRunTypeInterCalib";
     try {
@@ -529,7 +522,7 @@ xoap::MessageReference gem::hardware::amc::AMCManager::setRunTypeInterCalib(xoap
     return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "NotDone");
 }
 
-xoap::MessageReference gem::hardware::amc::AMCManager::updateRunParamCalib(xoap::MessageReference msg)
+xoap::MessageReference gem::hardware::AMCManager::updateRunParamCalib(xoap::MessageReference msg)
 {
     const std::string commandName = "updateRunParamCalib";
     try {
diff --git a/gemhardware/managers/src/amc/AMCManagerWeb.cpp b/gemhardware/managers/src/AMCManagerWeb.cpp
similarity index 65%
rename from gemhardware/managers/src/amc/AMCManagerWeb.cpp
rename to gemhardware/managers/src/AMCManagerWeb.cpp
index 7deb7bd7..0d851067 100644
--- a/gemhardware/managers/src/amc/AMCManagerWeb.cpp
+++ b/gemhardware/managers/src/AMCManagerWeb.cpp
@@ -1,29 +1,29 @@
-// AMCManagerWeb.cc
+/// @file AMCManagerWeb.cpp
 
-#include <memory>
+#include "gem/hardware/managers/AMCManagerWeb.h"
 
-#include "xcept/tools.h"
+#include "gem/hardware/devices/exception/Exception.h"
+#include "gem/hardware/managers/AMCManager.h"
 
-#include "gem/hardware/managers/amc/AMCManager.h"
-#include "gem/hardware/managers/amc/AMCManagerWeb.h"
+#include "xcept/tools.h"
 
-#include "gem/hardware/devices/exception/Exception.h"
+#include <memory>
 
-gem::hardware::amc::AMCManagerWeb::AMCManagerWeb(gem::hardware::amc::AMCManager* amcApp)
+gem::hardware::AMCManagerWeb::AMCManagerWeb(gem::hardware::AMCManager* amcApp)
     : gem::base::GEMWebApplication(amcApp)
 {
     // default constructor
 }
 
-gem::hardware::amc::AMCManagerWeb::~AMCManagerWeb()
+gem::hardware::AMCManagerWeb::~AMCManagerWeb()
 {
     // default destructor
 }
 
-void gem::hardware::amc::AMCManagerWeb::webDefault(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::webDefault(xgi::Input* in, xgi::Output* out)
 {
     if (p_gemFSMApp)
-        CMSGEMOS_DEBUG("current state is" << dynamic_cast<gem::hardware::amc::AMCManager*>(p_gemFSMApp)->getCurrentState());
+        CMSGEMOS_DEBUG("current state is" << dynamic_cast<gem::hardware::AMCManager*>(p_gemFSMApp)->getCurrentState());
     *out << cgicc::script().set("type", "text/javascript").set("src", "/gemdaq/gemhardware/html/scripts/amc/amc.js")
          << cgicc::script() << std::endl;
 
@@ -31,7 +31,7 @@ void gem::hardware::amc::AMCManagerWeb::webDefault(xgi::Input* in, xgi::Output*
 }
 
 /*To be filled in with the expert page code*/
-void gem::hardware::amc::AMCManagerWeb::expertPage(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::expertPage(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::expertPage");
     // fill this page with the expert views for the AMCManager
@@ -43,7 +43,7 @@ void gem::hardware::amc::AMCManagerWeb::expertPage(xgi::Input* in, xgi::Output*
 }
 
 /*To be filled in with the application page code*/
-void gem::hardware::amc::AMCManagerWeb::applicationPage(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::applicationPage(xgi::Input* in, xgi::Output* out)
 {
     std::string cardURL = "/" + p_gemApp->getApplicationDescriptor()->getURN() + "/cardPage";
     *out << "  <div class=\"xdaq-tab\" title=\"Card page\"/>" << std::endl;
@@ -52,18 +52,18 @@ void gem::hardware::amc::AMCManagerWeb::applicationPage(xgi::Input* in, xgi::Out
 }
 
 /*To be filled in with the card page code*/
-void gem::hardware::amc::AMCManagerWeb::registerDumpPage(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::registerDumpPage(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::registerDumpPage");
     // dump registers for a given AMC and display
 }
 
-void gem::hardware::amc::AMCManagerWeb::monitorPage(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::monitorPage(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::monitorPage");
 }
 
-void gem::hardware::amc::AMCManagerWeb::jsonUpdate(xgi::Input* in, xgi::Output* out)
+void gem::hardware::AMCManagerWeb::jsonUpdate(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::jsonUpdate");
 }
-- 
GitLab


From 4c137703772a634ef181f08c1675ab9264f58301 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 14:29:53 +0200
Subject: [PATCH 02/19] Remove unused bits in the AMCManager class

* Legacy configuration parameters and variables
* InfoSpace related calls
---
 doc/examples/xml/gem904daq04.xml            |   3 +-
 gemhardware/managers/interface/AMCManager.h |  65 ++++--------
 gemhardware/managers/src/AMCManager.cpp     | 107 ++++----------------
 3 files changed, 37 insertions(+), 138 deletions(-)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index 82030f1d..b7ce8e2f 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -111,10 +111,9 @@
         <AMCSlots xsi:type="xsd:string">2</AMCSlots>
         <AllAMCsInfo xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[12]">
           <GLIBInfo xsi:type="soapenc:Struct" soapenc:position="1"> <!--  position must be slot-1  -->
+            <present xsi:type="xsd:boolean">true</present>
             <crateID xsi:type="xsd:integer">1</crateID>
             <slot xsi:type="xsd:integer">2</slot>
-            <present xsi:type="xsd:boolean">true</present>
-            <sbitSource xsi:type="xsd:integer">5</sbitSource>
             <enableZS xsi:type="xsd:boolean">false</enableZS>
           </GLIBInfo>
         </AllAMCsInfo>
diff --git a/gemhardware/managers/interface/AMCManager.h b/gemhardware/managers/interface/AMCManager.h
index 8709353a..e2b6c4d7 100644
--- a/gemhardware/managers/interface/AMCManager.h
+++ b/gemhardware/managers/interface/AMCManager.h
@@ -17,7 +17,6 @@ namespace hardware {
     }
 
     using amc_shared_ptr = std::shared_ptr<gem::hardware::amc::HwGenericAMC>;
-    using is_toolbox_ptr = std::shared_ptr<gem::base::utils::GEMInfoSpaceToolBox>;
 
     class AMCManager : public gem::base::GEMFSMApplication {
 
@@ -27,36 +26,24 @@ namespace hardware {
         XDAQ_INSTANTIATOR();
 
         AMCManager(xdaq::ApplicationStub* s);
-
         virtual ~AMCManager();
 
     protected:
-        /* virtual void init() override; */
         void init();
 
-        virtual void actionPerformed(xdata::Event& event) override;
-
-        // state transitions FIXME: remove exception specifiers
-        virtual void initializeAction() override;
-        virtual void configureAction() override;
-        virtual void startAction() override;
-        virtual void pauseAction() override;
-        virtual void resumeAction() override;
-        virtual void stopAction() override;
-        virtual void haltAction() override;
-        virtual void resetAction() override;
-        // virtual void noAction()         override;
+        void actionPerformed(xdata::Event& event) override;
 
-        void failAction(toolbox::Event::Reference e);
-
-        virtual void resetAction(toolbox::Event::Reference e) override;
+        // State transitions
+        void initializeAction() override;
+        void configureAction() override;
+        void startAction() override;
+        void pauseAction() override;
+        void resumeAction() override;
+        void stopAction() override;
+        void haltAction() override;
+        void resetAction() override;
 
     private:
-        uint16_t m_amcEnableMask;
-
-        toolbox::task::WorkLoop* p_amc_wl; ///< paralelize the calls to different AMCs
-        toolbox::BSem m_amc_wl_semaphore[MAX_AMCS_PER_CRATE]; ///< do we need a semaphore for the workloop or each of them?
-
         class AMCInfo {
 
         public:
@@ -68,48 +55,32 @@ namespace hardware {
             xdata::Integer crateID; ///< Specifies the crate to which the OptoHybrid is connected
             xdata::Integer slotID; ///< Specifies the AMC slot to which the OptoHybrid is connected
 
-            // list of GTX links to enable in the DAQ
-            xdata::String gtxLinkEnableList;
-            xdata::UnsignedInteger32 gtxLinkEnableMask;
-
             // registers to set
-            xdata::Integer sbitSource;
             xdata::Boolean enableZS;
 
             inline std::string toString()
             {
                 std::stringstream os;
-                os << "present:" << present.toString() << std::endl
-                   << "crateID:" << crateID.toString() << std::endl
-                   << "slotID:" << slotID.toString() << std::endl
-
-                   << "gtxLinkEnableList:" << gtxLinkEnableList.toString() << std::endl
-                   << "gtxLinkEnableMask:" << std::hex << gtxLinkEnableMask.value_ << std::dec << std::endl
-
-                   << "sbitSource:0x" << std::hex << sbitSource.value_ << std::dec << std::endl
-                   << "enableZS:0x" << std::hex << enableZS.value_ << std::dec << std::endl
+                os << "present: " << present.toString() << std::endl
+                   << "crateID: " << crateID.toString() << std::endl
+                   << "slotID: " << slotID.toString() << std::endl
+                   << "enableZS: 0x" << std::hex << enableZS.value_ << std::dec << std::endl
                    << std::endl;
                 return os.str();
             };
         };
 
-        mutable gem::utils::Lock m_deviceLock; ///< [MAX_AMCS_PER_CRATE];
+        xdata::String m_amcSlots; ///<
+        xdata::Vector<xdata::Bag<AMCInfo>> m_amcInfo; ///< [MAX_AMCS_PER_CRATE];
 
         std::array<amc_shared_ptr, MAX_AMCS_PER_CRATE> m_amcs; ///< HwGLIB pointers to be managed
-        std::array<is_toolbox_ptr, MAX_AMCS_PER_CRATE> is_amcs; ///< AMC InfoSpace pointers to be managed
-
-        xdata::Vector<xdata::Bag<AMCInfo>> m_amcInfo; ///< [MAX_AMCS_PER_CRATE];
-        xdata::String m_amcSlots; ///<
-        xdata::String m_connectionFile; ///<
-        xdata::Boolean m_doPhaseShift; ///< Whether or not to do a phase shifting procedure during configuration
-        xdata::Boolean m_bc0LockPhaseShift; ///< Use BC0 to find the best phase during the phase shifting procedure
-        xdata::Boolean m_relockPhase; ///< Relock the phase during phase shifting
+        uint16_t m_amcEnableMask;
 
+        // Calibration scans
         uint32_t m_lastLatency; ///< Special variable for latency scan mode
         uint32_t m_lastVT1, m_lastVT2; ///< Special variable for threshold scan mode
 
         xoap::MessageReference setRunTypeInterCalib(xoap::MessageReference msg);
-        //xoap::MessageReference calibParamPrint(xoap::MessageReference msg);
         xoap::MessageReference updateRunParamCalib(xoap::MessageReference msg);
 
     }; // class AMCManager
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index 0ad084ec..f786ae66 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -25,7 +25,6 @@ gem::hardware::AMCManager::AMCInfo::AMCInfo()
     present = false;
     crateID = -1;
     slotID = -1;
-    sbitSource = 0;
     enableZS = true;
 }
 
@@ -34,38 +33,22 @@ void gem::hardware::AMCManager::AMCInfo::registerFields(xdata::Bag<gem::hardware
     bag->addField("crateID", &crateID);
     bag->addField("slot", &slotID);
     bag->addField("present", &present);
-    bag->addField("sbitSource", &sbitSource);
     bag->addField("enableZS", &enableZS);
 }
 
 gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
     : gem::base::GEMFSMApplication(stub)
     , m_amcEnableMask(0)
-    , m_doPhaseShift(false)
-    , m_bc0LockPhaseShift(false)
-    , m_relockPhase(true)
 {
     m_amcInfo.setSize(MAX_AMCS_PER_CRATE);
 
     p_appInfoSpace->fireItemAvailable("AllAMCsInfo", &m_amcInfo);
     p_appInfoSpace->fireItemAvailable("AMCSlots", &m_amcSlots);
-    p_appInfoSpace->fireItemAvailable("ConnectionFile", &m_connectionFile);
-    p_appInfoSpace->fireItemAvailable("DoPhaseShift", &m_doPhaseShift);
-    p_appInfoSpace->fireItemAvailable("BC0LockPhaseShift", &m_bc0LockPhaseShift);
-    p_appInfoSpace->fireItemAvailable("RelockPhase", &m_relockPhase);
 
     p_appInfoSpace->addItemRetrieveListener("AllAMCsInfo", this);
     p_appInfoSpace->addItemRetrieveListener("AMCSlots", this);
-    p_appInfoSpace->addItemRetrieveListener("ConnectionFile", this);
-    p_appInfoSpace->addItemRetrieveListener("DoPhaseShift", this);
-    p_appInfoSpace->addItemRetrieveListener("BC0LockPhaseShift", this);
-    p_appInfoSpace->addItemRetrieveListener("RelockPhase", this);
     p_appInfoSpace->addItemChangedListener("AllAMCsInfo", this);
     p_appInfoSpace->addItemChangedListener("AMCSlots", this);
-    p_appInfoSpace->addItemChangedListener("ConnectionFile", this);
-    p_appInfoSpace->addItemChangedListener("DoPhaseShift", this);
-    p_appInfoSpace->addItemChangedListener("BC0LockPhaseShift", this);
-    p_appInfoSpace->addItemChangedListener("RelockPhase", this);
 
     // initialize the AMC application objects
     CMSGEMOS_DEBUG("AMCManager::Connecting to the AMCManagerWeb interface");
@@ -86,7 +69,6 @@ gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
 
 gem::hardware::AMCManager::~AMCManager()
 {
-    // memory management, maybe not necessary here?
 }
 
 // This is the callback used for handling xdata:Event objects
@@ -116,18 +98,13 @@ void gem::hardware::AMCManager::actionPerformed(xdata::Event& event)
 
 void gem::hardware::AMCManager::init()
 {
-    // anything needed here?
 }
 
-// state transitions
+// State transitions
 void gem::hardware::AMCManager::initializeAction()
 {
-    CMSGEMOS_DEBUG("AMCManager::initializeAction begin");
-    //
-    // FIXME make me more streamlined
-    // this maybe shouldn't be done? Commenting out for now, but needs testing
-    //info.slotID  = slot+1;
-    //info.present = true;
+    CMSGEMOS_INFO("AMCManager::initializeAction begin");
+
     for (auto const& infoi : m_amcInfo) {
         auto&& info = infoi.bag;
 
@@ -142,19 +119,6 @@ void gem::hardware::AMCManager::initializeAction()
         std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d",
             info.crateID.value_,
             info.slotID.value_);
-        toolbox::net::URN hwCfgURN("urn:gem:hw:" + deviceName);
-
-        if (xdata::getInfoSpaceFactory()->hasItem(hwCfgURN.toString())) {
-            CMSGEMOS_DEBUG("AMCManager::initializeAction::infospace " << hwCfgURN.toString() << " already exists, getting");
-            is_amcs.at(slot) = is_toolbox_ptr(new gem::base::utils::GEMInfoSpaceToolBox(this,
-                xdata::getInfoSpaceFactory()->get(hwCfgURN.toString()),
-                true));
-        } else {
-            CMSGEMOS_DEBUG("AMCManager::initializeAction::infospace " << hwCfgURN.toString() << " does not exist, creating");
-            is_amcs.at(slot) = is_toolbox_ptr(new gem::base::utils::GEMInfoSpaceToolBox(this,
-                hwCfgURN.toString(),
-                true));
-        }
 
         try {
             CMSGEMOS_DEBUG("AMCManager::obtaining pointer to HwAMC");
@@ -164,18 +128,15 @@ void gem::hardware::AMCManager::initializeAction()
         }
         GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
         CMSGEMOS_DEBUG("AMCManager::connected");
-        // set the web view to be empty or grey
-        // if (!info.present.value_) continue;
-        // p_gemWebInterface->amcInSlot(slot);
     }
+
     CMSGEMOS_INFO("AMCManager::initializeAction end");
 }
 
 void gem::hardware::AMCManager::configureAction()
 {
-    CMSGEMOS_DEBUG("AMCManager::configureAction");
+    CMSGEMOS_INFO("AMCManager::configureAction begin");
 
-    // FIXME make me more streamlined
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         AMCInfo& info = m_amcInfo[slot].bag;
 
@@ -242,11 +203,6 @@ void gem::hardware::AMCManager::configureAction()
             // What else to do?
             // The DAQ module is already configured for physics in the common RPC method
         }
-        // what else is required for configuring the AMC?
-        // need to reset optical links?
-        // reset counters?
-        // setup run mode?
-        // setup DAQ mode?
     }
 
     CMSGEMOS_INFO("AMCManager::configureAction end");
@@ -254,6 +210,7 @@ void gem::hardware::AMCManager::configureAction()
 
 void gem::hardware::AMCManager::startAction()
 {
+    CMSGEMOS_INFO("AMCManager::startAction begin");
 
     if (m_scanInfo.bag.scanType.value_ == 2) {
         CMSGEMOS_INFO("AMCManager::startAction() " << std::endl
@@ -267,9 +224,6 @@ void gem::hardware::AMCManager::startAction()
         m_lastVT1 = m_scanInfo.bag.scanMin.value_;
     }
 
-    CMSGEMOS_INFO("AMCManager::startAction begin");
-    // what is required for starting the AMC?
-    // FIXME make me more streamlined
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
         AMCInfo& info = m_amcInfo[slot].bag;
@@ -298,13 +252,14 @@ void gem::hardware::AMCManager::startAction()
             XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
         }
     }
+
     CMSGEMOS_INFO("AMCManager::startAction end");
 }
 
 void gem::hardware::AMCManager::pauseAction()
 {
-    // what is required for pausing the AMC?
-    // FIXME make me more streamlined
+    CMSGEMOS_INFO("AMCManager::pauseAction begin");
+
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         // usleep(10);
         CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
@@ -374,14 +329,15 @@ void gem::hardware::AMCManager::pauseAction()
 
 void gem::hardware::AMCManager::resumeAction()
 {
-    // what is required for resuming the AMC?
+    CMSGEMOS_INFO("AMCManager::resumeAction begin");
+
     CMSGEMOS_INFO("AMCManager::resumeAction end");
 }
 
 void gem::hardware::AMCManager::stopAction()
 {
     CMSGEMOS_INFO("AMCManager::stopAction begin");
-    // FIXME make me more streamlined
+
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         // usleep(10);
         CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
@@ -400,14 +356,14 @@ void gem::hardware::AMCManager::stopAction()
             amc->resetDAQLink();
         }
     }
+
     CMSGEMOS_INFO("AMCManager::stopAction end");
 }
 
 void gem::hardware::AMCManager::haltAction()
 {
-    // what is required for halting the AMC?
-    CMSGEMOS_DEBUG("AMCManager::resetAction begin");
-    // FIXME make me more streamlined
+    CMSGEMOS_INFO("AMCManager::haltAction begin");
+
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
         AMCInfo& info = m_amcInfo[slot].bag;
@@ -423,16 +379,14 @@ void gem::hardware::AMCManager::haltAction()
             amc->setL1AEnable(false);
         }
     }
+
     CMSGEMOS_INFO("AMCManager::haltAction end");
 }
 
 void gem::hardware::AMCManager::resetAction()
 {
-    // what is required for resetting the AMC?
-    // unregister listeners and items in info spaces
+    CMSGEMOS_INFO("AMCManager::resetAction begin");
 
-    CMSGEMOS_DEBUG("AMCManager::resetAction begin");
-    // FIXME make me more streamlined
     for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
         // usleep(10);  // just for testing the timing of different applications
         CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
@@ -451,34 +405,9 @@ void gem::hardware::AMCManager::resetAction()
         // reset the hw monitor
 
         CMSGEMOS_DEBUG("AMCManager::looking for hwCfgInfoSpace items for AMC in slot " << (slot + 1));
-        toolbox::net::URN hwCfgURN("urn:gem:hw:" + toolbox::toString("gem-shelf%02d-amc%02d", info.crateID.value_, info.slotID.value_));
-
-        if (xdata::getInfoSpaceFactory()->hasItem(hwCfgURN.toString())) {
-            CMSGEMOS_DEBUG("AMCManager::revoking config parameters infospace");
-
-            // reset the hw infospace toolbox
-            is_amcs.at(slot)->reset();
-        } else {
-            CMSGEMOS_DEBUG("AMCManager::resetAction::infospace " << hwCfgURN.toString() << " does not exist, no further action");
-            continue;
-        }
     }
-    // gem::base::GEMFSMApplication::resetAction();
-    CMSGEMOS_INFO("AMCManager::resetAction end");
-}
 
-/*
-  void gem::hardware::AMCManager::noAction()
-  {
-  }
-*/
-
-void gem::hardware::AMCManager::failAction(toolbox::Event::Reference e)
-{
-}
-
-void gem::hardware::AMCManager::resetAction(toolbox::Event::Reference e)
-{
+    CMSGEMOS_INFO("AMCManager::resetAction end");
 }
 
 xoap::MessageReference gem::hardware::AMCManager::setRunTypeInterCalib(xoap::MessageReference msg)
-- 
GitLab


From c7bc057593f82adb781204a81746b407f9965d03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 14:52:54 +0200
Subject: [PATCH 03/19] Support a single board per AMC manager

---
 doc/examples/xml/gem904daq04.xml            |  16 +-
 gemhardware/managers/interface/AMCManager.h |  45 +-
 gemhardware/managers/src/AMCManager.cpp     | 480 +++++++-------------
 3 files changed, 182 insertions(+), 359 deletions(-)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index b7ce8e2f..5eb0f38a 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -107,16 +107,12 @@
 
     <xc:Application class="gem::hardware::AMCManager" id="30" instance="0" network="local">
       <properties xmlns="urn:xdaq-application:gem::hardware::AMCManager" xsi:type="soapenc:Struct">
-        <DisableMonitoring xsi:type="xsd:boolean">true</DisableMonitoring>
-        <AMCSlots xsi:type="xsd:string">2</AMCSlots>
-        <AllAMCsInfo xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[12]">
-          <GLIBInfo xsi:type="soapenc:Struct" soapenc:position="1"> <!--  position must be slot-1  -->
-            <present xsi:type="xsd:boolean">true</present>
-            <crateID xsi:type="xsd:integer">1</crateID>
-            <slot xsi:type="xsd:integer">2</slot>
-            <enableZS xsi:type="xsd:boolean">false</enableZS>
-          </GLIBInfo>
-        </AllAMCsInfo>
+        <!-- Hardware description -->
+        <crate xsi:type="xsd:unsignedInt">1</crate>
+        <slot xsi:type="xsd:unsignedInt">2</slot>
+
+        <!-- Configuration -->
+        <enableZS xsi:type="xsd:boolean">false</enableZS>
       </properties>
     </xc:Application>
 
diff --git a/gemhardware/managers/interface/AMCManager.h b/gemhardware/managers/interface/AMCManager.h
index e2b6c4d7..bc854a19 100644
--- a/gemhardware/managers/interface/AMCManager.h
+++ b/gemhardware/managers/interface/AMCManager.h
@@ -4,9 +4,11 @@
 #define GEM_HARDWARE_AMCMANAGER_H
 
 #include "gem/base/GEMFSMApplication.h"
-#include "gem/utils/soap/GEMSOAPToolBox.h"
 
-#include <array>
+#include "xdata/Boolean.h"
+#include "xdata/UnsignedInteger32.h"
+
+#include <memory>
 
 namespace gem {
 namespace hardware {
@@ -44,37 +46,14 @@ namespace hardware {
         void resetAction() override;
 
     private:
-        class AMCInfo {
-
-        public:
-            AMCInfo();
-            void registerFields(xdata::Bag<AMCManager::AMCInfo>* bag);
-
-            // monitoring information
-            xdata::Boolean present; ///< FIXME BAD USAGE
-            xdata::Integer crateID; ///< Specifies the crate to which the OptoHybrid is connected
-            xdata::Integer slotID; ///< Specifies the AMC slot to which the OptoHybrid is connected
-
-            // registers to set
-            xdata::Boolean enableZS;
-
-            inline std::string toString()
-            {
-                std::stringstream os;
-                os << "present: " << present.toString() << std::endl
-                   << "crateID: " << crateID.toString() << std::endl
-                   << "slotID: " << slotID.toString() << std::endl
-                   << "enableZS: 0x" << std::hex << enableZS.value_ << std::dec << std::endl
-                   << std::endl;
-                return os.str();
-            };
-        };
-
-        xdata::String m_amcSlots; ///<
-        xdata::Vector<xdata::Bag<AMCInfo>> m_amcInfo; ///< [MAX_AMCS_PER_CRATE];
-
-        std::array<amc_shared_ptr, MAX_AMCS_PER_CRATE> m_amcs; ///< HwGLIB pointers to be managed
-        uint16_t m_amcEnableMask;
+        // Hardware description
+        xdata::UnsignedInteger32 m_crate = 0; ///< Specifies the crate in which the AMC is located
+        xdata::UnsignedInteger32 m_slot = 0; ///< Specifies the slot in which the AMC is located
+
+        // Configuration
+        xdata::Boolean m_enableZS = false; ///< Enable the zero-suppression
+
+        amc_shared_ptr m_amc; ///< AMC hardware object
 
         // Calibration scans
         uint32_t m_lastLatency; ///< Special variable for latency scan mode
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index f786ae66..7198e703 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -20,51 +20,28 @@
 
 XDAQ_INSTANTIATOR_IMPL(gem::hardware::AMCManager);
 
-gem::hardware::AMCManager::AMCInfo::AMCInfo()
-{
-    present = false;
-    crateID = -1;
-    slotID = -1;
-    enableZS = true;
-}
-
-void gem::hardware::AMCManager::AMCInfo::registerFields(xdata::Bag<gem::hardware::AMCManager::AMCInfo>* bag)
-{
-    bag->addField("crateID", &crateID);
-    bag->addField("slot", &slotID);
-    bag->addField("present", &present);
-    bag->addField("enableZS", &enableZS);
-}
-
 gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
     : gem::base::GEMFSMApplication(stub)
-    , m_amcEnableMask(0)
 {
-    m_amcInfo.setSize(MAX_AMCS_PER_CRATE);
+    p_gemWebInterface = new gem::hardware::AMCManagerWeb(this);
 
-    p_appInfoSpace->fireItemAvailable("AllAMCsInfo", &m_amcInfo);
-    p_appInfoSpace->fireItemAvailable("AMCSlots", &m_amcSlots);
+    p_appInfoSpace->fireItemAvailable("crate", &m_crate);
+    p_appInfoSpace->fireItemAvailable("slot", &m_slot);
+    p_appInfoSpace->fireItemAvailable("enableZS", &m_enableZS);
 
-    p_appInfoSpace->addItemRetrieveListener("AllAMCsInfo", this);
-    p_appInfoSpace->addItemRetrieveListener("AMCSlots", this);
-    p_appInfoSpace->addItemChangedListener("AllAMCsInfo", this);
-    p_appInfoSpace->addItemChangedListener("AMCSlots", this);
+    p_appInfoSpace->addItemRetrieveListener("crate", this);
+    p_appInfoSpace->addItemRetrieveListener("slot", this);
+    p_appInfoSpace->addItemRetrieveListener("enableZS", this);
 
-    // initialize the AMC application objects
-    CMSGEMOS_DEBUG("AMCManager::Connecting to the AMCManagerWeb interface");
-    p_gemWebInterface = new gem::hardware::AMCManagerWeb(this);
-    CMSGEMOS_DEBUG("AMCManager::done");
+    p_appInfoSpace->addItemChangedListener("crate", this);
+    p_appInfoSpace->addItemChangedListener("slot", this);
+    p_appInfoSpace->addItemChangedListener("enableZS", this);
 
-    // set up the info hwCfgInfoSpace
     xoap::bind<gem::base::GEMApplication>(this, &gem::base::GEMApplication::calibParamRetrieve, "calibParamRetrieve", XDAQ_NS_URI);
-
-    //xoap::bind(this, &gem::hardware::AMCManager::calibParamPrint, "calibParamPrint", XDAQ_NS_URI);
     xoap::bind(this, &gem::hardware::AMCManager::setRunTypeInterCalib, "setRunTypeInterCalib", XDAQ_NS_URI);
     xoap::bind(this, &gem::hardware::AMCManager::updateRunParamCalib, "updateRunParamCalib", XDAQ_NS_URI);
 
     init();
-
-    // getApplicationDescriptor()->setAttribute("icon","/gemdaq/gemhardware/images/amc/AMCManager.png");
 }
 
 gem::hardware::AMCManager::~AMCManager()
@@ -75,24 +52,9 @@ gem::hardware::AMCManager::~AMCManager()
 void gem::hardware::AMCManager::actionPerformed(xdata::Event& event)
 {
     if (event.type() == "setDefaultValues" || event.type() == "urn:xdaq-event:setDefaultValues") {
-        CMSGEMOS_DEBUG("AMCManager::actionPerformed() setDefaultValues"
-            << "Default configuration values have been loaded from xml profile");
-        m_amcEnableMask = gem::hardware::utils::parseAMCEnableList(m_amcSlots.toString(),
-            // &m_gemLogger);
-            m_gemLogger);
-        CMSGEMOS_INFO("AMCManager::actionPerformed() Parsed AMCEnableList m_amcSlots = " << m_amcSlots.toString()
-                                                                                         << " to slotMask 0x" << std::hex << m_amcEnableMask << std::dec);
-
-        // how to handle passing in various values nested in a vector in a bag
-        for (auto& slot : m_amcInfo) {
-            if (slot.bag.crateID.value_ > -1) {
-                slot.bag.present = true;
-                CMSGEMOS_DEBUG("AMCManager::Found attribute:" << slot.bag.toString());
-            }
-        }
+        CMSGEMOS_DEBUG("AMCManager::actionPerformed() setDefaultValues");
     }
 
-    // FIXME update monitoring variables?
     gem::base::GEMApplication::actionPerformed(event);
 }
 
@@ -105,30 +67,12 @@ void gem::hardware::AMCManager::initializeAction()
 {
     CMSGEMOS_INFO("AMCManager::initializeAction begin");
 
-    for (auto const& infoi : m_amcInfo) {
-        auto&& info = infoi.bag;
-
-        // check the config file if there should be a AMC in the specified slot, if not, do not initialize
-        if (!info.present)
-            continue;
+    std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_);
 
-        uint32_t slot = info.slotID.value_ - 1;
-        CMSGEMOS_DEBUG("AMCManager::creating pointer to card in slot " << (slot + 1));
-
-        // create the cfgInfoSpace object (qualified vs non?)
-        std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d",
-            info.crateID.value_,
-            info.slotID.value_);
-
-        try {
-            CMSGEMOS_DEBUG("AMCManager::obtaining pointer to HwAMC");
-            m_amcs.at(slot) = amc_shared_ptr(new gem::hardware::amc::HwGenericAMC(deviceName));
-            amc_shared_ptr amc = m_amcs.at(slot);
-            // TODO check whether the AMC is accessible
-        }
-        GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
-        CMSGEMOS_DEBUG("AMCManager::connected");
+    try {
+        m_amc = std::make_shared<gem::hardware::amc::HwGenericAMC>(deviceName);
     }
+    GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
 
     CMSGEMOS_INFO("AMCManager::initializeAction end");
 }
@@ -137,72 +81,58 @@ void gem::hardware::AMCManager::configureAction()
 {
     CMSGEMOS_INFO("AMCManager::configureAction begin");
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        AMCInfo& info = m_amcInfo[slot].bag;
-
-        if (!info.present)
-            continue;
-
-        amc_shared_ptr amc = m_amcs.at(slot);
-
-        //Recover AMC: check clocks, reload AMC FW, restart RPC sevice
-        amc->recoverAMC();
+    // Recover AMC: check clocks, reload AMC FW, restart RPC sevice
+    m_amc->recoverAMC();
 
-        if (!amc->isHwConnected()) {
-            std::stringstream msg;
-            msg << "AMCManager::configureAction AMC in slot " << (slot + 1) << " is not connected";
-            CMSGEMOS_ERROR(msg.str());
-            // fireEvent("Fail");
-            // TODO Attempt an AMC recovery here (check clocks, reload AMC FW, restart RPC sevice etc...)? Or it should be done at the init stage?
-            XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
-        }
+    if (!m_amc->isHwConnected()) {
+        std::stringstream msg;
+        msg << "AMCManager::configureAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(msg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
+    }
 
-        CMSGEMOS_INFO("AMCManager::configureAction: establish front end communication");
-        try {
-            amc->establishFrontEndCommunication();
-        }
-        GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
+    CMSGEMOS_INFO("AMCManager::configureAction: establish front end communication");
+    try {
+        m_amc->establishFrontEndCommunication();
+    }
+    GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
-        const bool inputEnableMask = amc->connectedLinks();
-        const bool enableZS = info.enableZS.value_;
-        try { // FIXME if we fail, do we go to error?
-            amc->configureDAQModule(inputEnableMask, enableZS);
-        }
-        GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
+    const bool inputEnableMask = m_amc->connectedLinks();
+    try {
+        m_amc->configureDAQModule(inputEnableMask, m_enableZS.value_);
+    }
+    GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
-        if (m_scanInfo.bag.scanType.value_ == 2) {
+    if (m_scanInfo.bag.scanType.value_ == 2) {
 
-            amc->setDAQLinkRunType(0x2);
-            uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (m_scanInfo.bag.scanMin.value_ & 0x3ff));
-            //                       isExtTrig; isCurrentPulse; CFG_CAL_DAC;   MSPL/\;
+        m_amc->setDAQLinkRunType(0x2);
+        uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (m_scanInfo.bag.scanMin.value_ & 0x3ff));
+        //                       isExtTrig; isCurrentPulse; CFG_CAL_DAC;   MSPL/\;
 
-            CMSGEMOS_INFO("AMCManager::configureAction AMC runParams :" << runParams); //CG: TO be removed
-            amc->setDAQLinkRunParameters(runParams);
-            CMSGEMOS_INFO("AMCManager::configureAction::  m_scanInfo.bag.calMode.value_ " << m_scanInfo.bag.calMode.value_); ///CG remove
-            //If calibration format mode invoked for data
+        CMSGEMOS_INFO("AMCManager::configureAction AMC runParams :" << runParams); //CG: TO be removed
+        m_amc->setDAQLinkRunParameters(runParams);
+        CMSGEMOS_INFO("AMCManager::configureAction::  m_scanInfo.bag.calMode.value_ " << m_scanInfo.bag.calMode.value_); ///CG remove
 
-            // setting caldata format here; and in OHmanager set the channels for the calmode
-            amc->configureAMCCalDataFormat(m_scanInfo.bag.calMode.value_);
+        // If calibration format mode invoked for data
+        // setting caldata format here; and in OHmanager set the channels for the calmode
+        m_amc->configureAMCCalDataFormat(m_scanInfo.bag.calMode.value_);
 
-            // taken from Brian's macro
-            amc->writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
-            amc->writeReg("GEM_AMC.TTC.CTRL.CALIBRATION_MODE", 0x0);
+        // taken from Brian's macro
+        m_amc->writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
+        m_amc->writeReg("GEM_AMC.TTC.CTRL.CALIBRATION_MODE", 0x0);
 
-            CMSGEMOS_INFO("AMCManager::configureAction:: exiting latency");
+        CMSGEMOS_INFO("AMCManager::configureAction:: exiting latency");
 
-        } else if (m_scanInfo.bag.scanType.value_ == 3) {
-            uint32_t initialVT1 = m_scanInfo.bag.scanMin.value_;
-            uint32_t initialVT2 = 0; // std::max(0,(uint32_t)m_scanInfo.bag.scanMax.value_);
-            CMSGEMOS_INFO("AMCManager::configureAction FIRST VT1 " << initialVT1 << " VT2 " << initialVT2);
-
-            amc->setDAQLinkRunType(0x3);
-            // amc->setDAQLinkRunParameter(0x1,latency);  // set this at start so DQM has it?
-            amc->setDAQLinkRunParameter(0x2, initialVT1);
-            amc->setDAQLinkRunParameter(0x3, initialVT2);
-        } else {
-            // What else to do?
-            // The DAQ module is already configured for physics in the common RPC method
-        }
+    } else if (m_scanInfo.bag.scanType.value_ == 3) {
+        uint32_t initialVT1 = m_scanInfo.bag.scanMin.value_;
+        uint32_t initialVT2 = 0; // std::max(0,(uint32_t)m_scanInfo.bag.scanMax.value_);
+        CMSGEMOS_INFO("AMCManager::configureAction FIRST VT1 " << initialVT1 << " VT2 " << initialVT2);
+
+        m_amc->setDAQLinkRunType(0x3);
+        // m_amc->setDAQLinkRunParameter(0x1,latency);  // set this at start so DQM has it?
+        m_amc->setDAQLinkRunParameter(0x2, initialVT1);
+        m_amc->setDAQLinkRunParameter(0x3, initialVT2);
+    } else {
     }
 
     CMSGEMOS_INFO("AMCManager::configureAction end");
@@ -224,33 +154,23 @@ void gem::hardware::AMCManager::startAction()
         m_lastVT1 = m_scanInfo.bag.scanMin.value_;
     }
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-        AMCInfo& info = m_amcInfo[slot].bag;
+    if (m_amc->isHwConnected()) {
+        CMSGEMOS_DEBUG("connected a card in slot " << m_slot.value_);
 
-        if (!info.present)
-            continue;
+        //FIXME shall be one RPC call?
+        m_amc->ttcModuleReset();
 
-        amc_shared_ptr amc = m_amcs.at(slot);
-        if (amc->isHwConnected()) {
-            CMSGEMOS_DEBUG("connected a card in slot " << (slot + 1));
+        // This is the most sensible order
+        // 1. Reset, 2. Activation, 3. Start
+        m_amc->resetDAQLink();
+        m_amc->enableDAQLink();
+        m_amc->setL1AEnable(true);
 
-            //FIXME shall be one RPC call?
-            amc->ttcModuleReset();
-
-            // This is the most sensible order
-            // 1. Reset, 2. Activation, 3. Start
-            amc->resetDAQLink();
-            amc->enableDAQLink();
-            amc->setL1AEnable(true);
-
-        } else {
-            std::stringstream msg;
-            msg << "AMCManager::startAction AMC in slot " << (slot + 1) << " is not connected";
-            CMSGEMOS_ERROR(msg.str());
-            // fireEvent("Fail");
-            XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
-        }
+    } else {
+        std::stringstream msg;
+        msg << "AMCManager::startAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(msg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
     }
 
     CMSGEMOS_INFO("AMCManager::startAction end");
@@ -260,57 +180,44 @@ void gem::hardware::AMCManager::pauseAction()
 {
     CMSGEMOS_INFO("AMCManager::pauseAction begin");
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        // usleep(10);
-        CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-        AMCInfo& info = m_amcInfo[slot].bag;
-
-        if (!info.present)
-            continue;
+    if (m_amc->isHwConnected()) {
+        CMSGEMOS_DEBUG("connected a card in slot " << m_slot.value_);
 
-        amc_shared_ptr amc = m_amcs.at(slot);
-        if (amc->isHwConnected()) {
-
-            //FIXME what should be done here? Disable triggers? wait for AMC to stop building events?
-            CMSGEMOS_DEBUG("connected a card in slot " << (slot + 1));
-
-            if (m_scanInfo.bag.scanType.value_ == 2) {
-                uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
-                CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan AMC" << (slot + 1) << " Latency " << (int)updatedLatency);
-
-                // wait for events to finish building
-                while (!amc->l1aFIFOIsEmpty()) {
-                    CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << (slot + 1) << " to finish building events");
-                    usleep(10);
-                }
-                CMSGEMOS_DEBUG("AMCManager::pauseAction AMC" << (slot + 1) << " finished building events, updating run parameter "
-                                                             << (int)updatedLatency);
-                amc->setDAQLinkRunParameter(0x1, updatedLatency);
-            } else if (m_scanInfo.bag.scanType.value_ == 3) {
-                uint8_t updatedVT1 = m_lastVT1 + m_stepSize.value_;
-                uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
-                CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan AMC" << (slot + 1) << ""
-                                                                          << " VT1 " << (int)updatedVT1
-                                                                          << " VT2 " << (int)updatedVT2);
+        if (m_scanInfo.bag.scanType.value_ == 2) {
+            uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
+            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan AMC" << m_slot.value_ << " Latency " << (int)updatedLatency);
 
-                // wait for events to finish building
-                while (!amc->l1aFIFOIsEmpty()) {
-                    CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << (slot + 1) << " to finish building events");
-                    usleep(10);
-                }
-                CMSGEMOS_DEBUG("AMCManager::pauseAction finished AMC" << (slot + 1) << " building events, updating VT1 " << (int)updatedVT1
-                                                                      << " and VT2 " << (int)updatedVT2);
-                amc->setDAQLinkRunParameter(0x2, updatedVT1);
-                amc->setDAQLinkRunParameter(0x3, updatedVT2);
+            // wait for events to finish building
+            while (!m_amc->l1aFIFOIsEmpty()) {
+                CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
+                usleep(10);
             }
-
-        } else {
-            std::stringstream msg;
-            msg << "AMCManager::pauseAction AMC in slot " << (slot + 1) << " is not connected";
-            CMSGEMOS_ERROR(msg.str());
-            // fireEvent("Fail");
-            XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
+            CMSGEMOS_DEBUG("AMCManager::pauseAction AMC" << m_slot.value_ << " finished building events, updating run parameter "
+                                                         << (int)updatedLatency);
+            m_amc->setDAQLinkRunParameter(0x1, updatedLatency);
+        } else if (m_scanInfo.bag.scanType.value_ == 3) {
+            uint8_t updatedVT1 = m_lastVT1 + m_stepSize.value_;
+            uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
+            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan AMC" << m_slot.value_ << ""
+                                                                      << " VT1 " << (int)updatedVT1
+                                                                      << " VT2 " << (int)updatedVT2);
+
+            // wait for events to finish building
+            while (!m_amc->l1aFIFOIsEmpty()) {
+                CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
+                usleep(10);
+            }
+            CMSGEMOS_DEBUG("AMCManager::pauseAction finished AMC" << m_slot.value_ << " building events, updating VT1 " << (int)updatedVT1
+                                                                  << " and VT2 " << (int)updatedVT2);
+            m_amc->setDAQLinkRunParameter(0x2, updatedVT1);
+            m_amc->setDAQLinkRunParameter(0x3, updatedVT2);
         }
+
+    } else {
+        std::stringstream msg;
+        msg << "AMCManager::pauseAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(msg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
     }
 
     // Update the scan parameters
@@ -338,23 +245,10 @@ void gem::hardware::AMCManager::stopAction()
 {
     CMSGEMOS_INFO("AMCManager::stopAction begin");
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        // usleep(10);
-        CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-        AMCInfo& info = m_amcInfo[slot].bag;
-
-        if (!info.present)
-            continue;
-
-        amc_shared_ptr amc = m_amcs.at(slot);
-        if (amc->isHwConnected()) {
-
-            // what is required for stopping the AMC?
-            // FIXME temporarily inhibit triggers at the AMC
-            amc->setL1AEnable(false);
-            amc->disableDAQLink();
-            amc->resetDAQLink();
-        }
+    if (m_amc->isHwConnected()) {
+        m_amc->setL1AEnable(false);
+        m_amc->disableDAQLink();
+        m_amc->resetDAQLink();
     }
 
     CMSGEMOS_INFO("AMCManager::stopAction end");
@@ -364,20 +258,8 @@ void gem::hardware::AMCManager::haltAction()
 {
     CMSGEMOS_INFO("AMCManager::haltAction begin");
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-        AMCInfo& info = m_amcInfo[slot].bag;
-
-        if (!info.present)
-            continue;
-
-        amc_shared_ptr amc = m_amcs.at(slot);
-        if (amc->isHwConnected()) {
-
-            // what is required for halting the AMC?
-            // FIXME temporarily inhibit triggers at the AMC
-            amc->setL1AEnable(false);
-        }
+    if (m_amc->isHwConnected()) {
+        m_amc->setL1AEnable(false);
     }
 
     CMSGEMOS_INFO("AMCManager::haltAction end");
@@ -387,26 +269,12 @@ void gem::hardware::AMCManager::resetAction()
 {
     CMSGEMOS_INFO("AMCManager::resetAction begin");
 
-    for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        // usleep(10);  // just for testing the timing of different applications
-        CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-        AMCInfo& info = m_amcInfo[slot].bag;
-
-        if (!info.present)
-            continue;
-
-        amc_shared_ptr amc = m_amcs.at(slot);
-        if (amc->isHwConnected()) {
-
-            // what is required for resetting the AMC?
-            // FIXME temporarily inhibit triggers at the AMC
-            amc->setL1AEnable(false);
-        }
-        // reset the hw monitor
-
-        CMSGEMOS_DEBUG("AMCManager::looking for hwCfgInfoSpace items for AMC in slot " << (slot + 1));
+    if (m_amc->isHwConnected()) {
+        m_amc->setL1AEnable(false);
     }
 
+    CMSGEMOS_DEBUG("AMCManager::looking for hwCfgInfoSpace items for AMC in slot " << m_slot.value_);
+
     CMSGEMOS_INFO("AMCManager::resetAction end");
 }
 
@@ -414,29 +282,18 @@ xoap::MessageReference gem::hardware::AMCManager::setRunTypeInterCalib(xoap::Mes
 {
     const std::string commandName = "setRunTypeInterCalib";
     try {
-        // what is required for pausing the AMC?
-        // FIXME make me more streamlined
-        for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-            CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-            AMCInfo& info = m_amcInfo[slot].bag;
-
-            if (!info.present)
-                continue;
-
-            amc_shared_ptr amc = m_amcs.at(slot);
-            if (amc->isHwConnected()) {
-                // ///should it wait for the event to finish building : CG?????
-                while (!amc->l1aFIFOIsEmpty()) {
-                    CMSGEMOS_DEBUG("AMCManager::setRunTypeInterCalib waiting for AMC" << (slot + 1) << " to finish building events");
-                    usleep(10);
-                }
-                if (m_scanInfo.bag.scanType.value_ == 2) {
+        if (m_amc->isHwConnected()) {
+            // ///should it wait for the event to finish building : CG?????
+            while (!m_amc->l1aFIFOIsEmpty()) {
+                CMSGEMOS_DEBUG("AMCManager::setRunTypeInterCalib waiting for AMC" << m_slot.value_ << " to finish building events");
+                usleep(10);
+            }
+            if (m_scanInfo.bag.scanType.value_ == 2) {
 
-                    amc->setDAQLinkRunType(0x0);
+                m_amc->setDAQLinkRunType(0x0);
 
-                } else {
-                    CMSGEMOS_ERROR("AMCManager::setRunTypeInterCalib AMC in slot " << (slot + 1) << " is not connected");
-                }
+            } else {
+                CMSGEMOS_ERROR("AMCManager::setRunTypeInterCalib AMC in slot " << m_slot.value_ << " is not connected");
             }
         }
 
@@ -455,56 +312,47 @@ xoap::MessageReference gem::hardware::AMCManager::updateRunParamCalib(xoap::Mess
 {
     const std::string commandName = "updateRunParamCalib";
     try {
-        for (unsigned slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-            CMSGEMOS_DEBUG("AMCManager::looping over slots(" << (slot + 1) << ") and finding infospace items");
-            AMCInfo& info = m_amcInfo[slot].bag;
-
-            if (!info.present)
-                continue;
-
-            amc_shared_ptr amc = m_amcs.at(slot);
-            if (amc->isHwConnected()) {
-                CMSGEMOS_DEBUG("connected a card in slot " << (slot + 1));
-
-                if (m_scanInfo.bag.scanType.value_ == 2) {
-                    // ///should it wait for the event to finish building : CG?????
-                    while (!amc->l1aFIFOIsEmpty()) {
-                        CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib waiting for AMC" << (slot + 1) << " to finish building events");
-                        usleep(10);
-                    }
-
-                    uint32_t updatedLatency = m_lastLatency + m_scanInfo.bag.stepSize.value_;
-
-                    CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib AMC" << (slot + 1) << " finished building events, updating run parameter "
-                                                                         << (int)updatedLatency);
-                    //updating the runparam as descrbed here: https://github.com/cms-gem-daq-project/cmsgemos/pull/302
-                    uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (updatedLatency & 0x3ff));
-
-                    amc->setDAQLinkRunType(0x2);
-                    amc->setDAQLinkRunParameters(runParams);
-
-                } else if (m_scanInfo.bag.scanType.value_ == 3) {
-                    uint8_t updatedVT1 = m_lastVT1 + m_scanInfo.bag.stepSize.value_;
-                    uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
-                    CMSGEMOS_INFO("AMCManager::updateRunParamCalib ThresholdScan AMC" << (slot + 1) << ""
-                                                                                      << " VT1 " << (int)updatedVT1
-                                                                                      << " VT2 " << (int)updatedVT2);
-
-                    // wait for events to finish building
-                    while (!amc->l1aFIFOIsEmpty()) {
-                        CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib waiting for AMC" << (slot + 1) << " to finish building events");
-                        usleep(10);
-                    }
-                    CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib finished AMC" << (slot + 1) << " building events, updating VT1 " << (int)updatedVT1
-                                                                                  << " and VT2 " << (int)updatedVT2);
-                    amc->setDAQLinkRunParameter(0x2, updatedVT1);
-                    amc->setDAQLinkRunParameter(0x3, updatedVT2);
+        if (m_amc->isHwConnected()) {
+            CMSGEMOS_DEBUG("connected a card in slot " << m_slot.value_);
+
+            if (m_scanInfo.bag.scanType.value_ == 2) {
+                // ///should it wait for the event to finish building : CG?????
+                while (!m_amc->l1aFIFOIsEmpty()) {
+                    CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib waiting for AMC" << m_slot.value_ << " to finish building events");
+                    usleep(10);
                 }
-            } else {
-                std::stringstream msg;
-                msg << "AMCManager::updateRunParamCalib AMC in slot " << (slot + 1) << " is not connected";
-                CMSGEMOS_ERROR(msg.str());
+
+                uint32_t updatedLatency = m_lastLatency + m_scanInfo.bag.stepSize.value_;
+
+                CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib AMC" << m_slot.value_ << " finished building events, updating run parameter "
+                                                                     << (int)updatedLatency);
+                //updating the runparam as descrbed here: https://github.com/cms-gem-daq-project/cmsgemos/pull/302
+                uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (updatedLatency & 0x3ff));
+
+                m_amc->setDAQLinkRunType(0x2);
+                m_amc->setDAQLinkRunParameters(runParams);
+
+            } else if (m_scanInfo.bag.scanType.value_ == 3) {
+                uint8_t updatedVT1 = m_lastVT1 + m_scanInfo.bag.stepSize.value_;
+                uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
+                CMSGEMOS_INFO("AMCManager::updateRunParamCalib ThresholdScan AMC" << m_slot.value_ << ""
+                                                                                  << " VT1 " << (int)updatedVT1
+                                                                                  << " VT2 " << (int)updatedVT2);
+
+                // wait for events to finish building
+                while (!m_amc->l1aFIFOIsEmpty()) {
+                    CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib waiting for AMC" << m_slot.value_ << " to finish building events");
+                    usleep(10);
+                }
+                CMSGEMOS_DEBUG("AMCManager::updateRunParamCalib finished AMC" << m_slot.value_ << " building events, updating VT1 " << (int)updatedVT1
+                                                                              << " and VT2 " << (int)updatedVT2);
+                m_amc->setDAQLinkRunParameter(0x2, updatedVT1);
+                m_amc->setDAQLinkRunParameter(0x3, updatedVT2);
             }
+        } else {
+            std::stringstream msg;
+            msg << "AMCManager::updateRunParamCalib AMC in slot " << m_slot.value_ << " is not connected";
+            CMSGEMOS_ERROR(msg.str());
         }
 
         // Update the scan parameters
-- 
GitLab


From 5a6139b17cfc121b6c6de09e69d48e5a4a238b1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 16:36:43 +0200
Subject: [PATCH 04/19] Merge the OptoHybrid manager into the AMC manager

---
 doc/examples/xml/gem904daq04.xml              |  14 +-
 gemhardware/managers/CMakeLists.txt           |   2 -
 gemhardware/managers/interface/AMCManager.h   |   8 +
 .../managers/interface/AMCManagerWeb.h        |  24 +-
 .../interface/optohybrid/OptoHybridManager.h  | 110 -----
 .../optohybrid/OptoHybridManagerWeb.h         |  43 --
 gemhardware/managers/src/AMCManager.cpp       | 360 +++++++++++---
 gemhardware/managers/src/AMCManagerWeb.cpp    |  15 +-
 .../src/optohybrid/OptoHybridManager.cpp      | 460 ------------------
 .../src/optohybrid/OptoHybridManagerWeb.cpp   |  63 ---
 gemsupervisor/src/GEMSupervisor.cpp           |  60 +--
 11 files changed, 344 insertions(+), 815 deletions(-)
 delete mode 100644 gemhardware/managers/interface/optohybrid/OptoHybridManager.h
 delete mode 100644 gemhardware/managers/interface/optohybrid/OptoHybridManagerWeb.h
 delete mode 100644 gemhardware/managers/src/optohybrid/OptoHybridManager.cpp
 delete mode 100644 gemhardware/managers/src/optohybrid/OptoHybridManagerWeb.cpp

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index 5eb0f38a..48c34351 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -110,25 +110,13 @@
         <!-- Hardware description -->
         <crate xsi:type="xsd:unsignedInt">1</crate>
         <slot xsi:type="xsd:unsignedInt">2</slot>
+        <optohybridMask xsi:type="xsd:unsignedInt">0x1</optohybridMask>
 
         <!-- Configuration -->
         <enableZS xsi:type="xsd:boolean">false</enableZS>
       </properties>
     </xc:Application>
 
-    <xc:Application class="gem::hardware::optohybrid::OptoHybridManager" id="50" instance="0" network="local">
-      <properties xmlns="urn:xdaq-application:gem::hardware::optohybrid::OptoHybridManager" xsi:type="soapenc:Struct">
-        <AllOptoHybridsInfo xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[144]">
-          <OptoHybridInfo xsi:type="soapenc:Struct" soapenc:position="12"> <!-- position must be (slot-1)*12+link -->
-            <crateID xsi:type="xsd:integer">1</crateID>
-            <slot xsi:type="xsd:integer">2</slot>
-            <link xsi:type="xsd:integer">0</link>
-            <present xsi:type="xsd:boolean">true</present>
-          </OptoHybridInfo>
-        </AllOptoHybridsInfo>
-      </properties>
-    </xc:Application>
-
     <xc:Module>${CMSGEMOS_LIBDIR}/libgemcalibration.so</xc:Module>
 
     <xc:Application class="gem::calibration::Calibration" id="17" instance="0" network="local">
diff --git a/gemhardware/managers/CMakeLists.txt b/gemhardware/managers/CMakeLists.txt
index 14521e0f..9218b213 100644
--- a/gemhardware/managers/CMakeLists.txt
+++ b/gemhardware/managers/CMakeLists.txt
@@ -7,8 +7,6 @@ cmsgemos_add_module(
     amc13/AMC13Manager.cpp
     amc13/AMC13ManagerWeb.cpp
     amc13/AMC13Readout.cpp
-    optohybrid/OptoHybridManager.cpp
-    optohybrid/OptoHybridManagerWeb.cpp
 )
 
 target_link_libraries(gemhardware_managers PUBLIC gembase)
diff --git a/gemhardware/managers/interface/AMCManager.h b/gemhardware/managers/interface/AMCManager.h
index bc854a19..ea2e4ffd 100644
--- a/gemhardware/managers/interface/AMCManager.h
+++ b/gemhardware/managers/interface/AMCManager.h
@@ -17,8 +17,12 @@ namespace hardware {
     namespace amc {
         class HwGenericAMC;
     }
+    namespace optohybrid {
+        class HwOptoHybrid;
+    }
 
     using amc_shared_ptr = std::shared_ptr<gem::hardware::amc::HwGenericAMC>;
+    using optohybrid_shared_ptr = std::shared_ptr<gem::hardware::optohybrid::HwOptoHybrid>;
 
     class AMCManager : public gem::base::GEMFSMApplication {
 
@@ -49,11 +53,14 @@ namespace hardware {
         // Hardware description
         xdata::UnsignedInteger32 m_crate = 0; ///< Specifies the crate in which the AMC is located
         xdata::UnsignedInteger32 m_slot = 0; ///< Specifies the slot in which the AMC is located
+        xdata::UnsignedInteger32 m_optohybridMask = 0x0; ///< OptoHybrids to use in the run
 
         // Configuration
         xdata::Boolean m_enableZS = false; ///< Enable the zero-suppression
 
         amc_shared_ptr m_amc; ///< AMC hardware object
+        std::array<optohybrid_shared_ptr, MAX_OPTOHYBRIDS_PER_AMC> m_optohybrids; ///< OptoHybrid hardware objects
+        std::array<uint32_t, MAX_OPTOHYBRIDS_PER_AMC> m_vfatMask; ///< Automatically determined VFAT mask
 
         // Calibration scans
         uint32_t m_lastLatency; ///< Special variable for latency scan mode
@@ -61,6 +68,7 @@ namespace hardware {
 
         xoap::MessageReference setRunTypeInterCalib(xoap::MessageReference msg);
         xoap::MessageReference updateRunParamCalib(xoap::MessageReference msg);
+        xoap::MessageReference updateScanValueCalib(xoap::MessageReference msg);
 
     }; // class AMCManager
 } // namespace gem::hardware
diff --git a/gemhardware/managers/interface/AMCManagerWeb.h b/gemhardware/managers/interface/AMCManagerWeb.h
index 3b4ad75f..7b9e9cac 100644
--- a/gemhardware/managers/interface/AMCManagerWeb.h
+++ b/gemhardware/managers/interface/AMCManagerWeb.h
@@ -15,30 +15,16 @@ namespace hardware {
 
     public:
         AMCManagerWeb(AMCManager* amcApp);
-
         virtual ~AMCManagerWeb();
 
     protected:
-        virtual void webDefault(xgi::Input* in, xgi::Output* out);
-
-        virtual void monitorPage(xgi::Input* in, xgi::Output* out);
-
-        virtual void expertPage(xgi::Input* in, xgi::Output* out);
-
-        virtual void applicationPage(xgi::Input* in, xgi::Output* out);
-
-        virtual void jsonUpdate(xgi::Input* in, xgi::Output* out);
-
-        /* void buildCardSummaryTable(xgi::Input* in, xgi::Output* out); */
-
-        /* void cardPage(xgi::Input* in, xgi::Output* out); */
+        void webDefault(xgi::Input* in, xgi::Output* out) override;
+        void monitorPage(xgi::Input* in, xgi::Output* out) override;
+        void expertPage(xgi::Input* in, xgi::Output* out) override;
+        void applicationPage(xgi::Input* in, xgi::Output* out) override;
+        void jsonUpdate(xgi::Input* in, xgi::Output* out) override;
 
         void registerDumpPage(xgi::Input* in, xgi::Output* out);
-
-    private:
-        size_t activeCard;
-
-        //AMCManagerWeb(AMCManagerWeb const&);
     };
 
 } // namespace gem::hardware
diff --git a/gemhardware/managers/interface/optohybrid/OptoHybridManager.h b/gemhardware/managers/interface/optohybrid/OptoHybridManager.h
deleted file mode 100644
index 6583eef4..00000000
--- a/gemhardware/managers/interface/optohybrid/OptoHybridManager.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/// @file OptoHybridManager.h
-
-#ifndef GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGER_H
-#define GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGER_H
-
-#include <array>
-#include <set>
-
-#include "gem/base/GEMFSMApplication.h"
-// #include "gem/hardware/optohybrid/OptoHybridSettings.h"
-
-#include "gem/utils/soap/GEMSOAPToolBox.h"
-
-namespace gem {
-namespace hardware {
-    namespace optohybrid {
-
-        class HwOptoHybrid;
-        class OptoHybridManagerWeb;
-
-        using optohybrid_shared_ptr = std::shared_ptr<HwOptoHybrid>;
-        using is_toolbox_ptr = std::shared_ptr<gem::base::utils::GEMInfoSpaceToolBox>;
-
-        class OptoHybridManager : public gem::base::GEMFSMApplication {
-
-            friend class OptoHybridManagerWeb;
-
-        public:
-            XDAQ_INSTANTIATOR();
-
-            OptoHybridManager(xdaq::ApplicationStub* s);
-
-            virtual ~OptoHybridManager();
-
-        protected:
-            /* virtual void init() override; */
-            void init();
-
-            virtual void actionPerformed(xdata::Event& event) override;
-
-            // state transitions
-            virtual void initializeAction() override;
-            virtual void configureAction() override;
-            virtual void startAction() override;
-            virtual void pauseAction() override;
-            virtual void resumeAction() override;
-            virtual void stopAction() override;
-            virtual void haltAction() override;
-            virtual void resetAction() override;
-            // virtual void noAction()         override;
-
-            void failAction(toolbox::Event::Reference e);
-
-            virtual void resetAction(toolbox::Event::Reference e) override;
-
-            xoap::MessageReference updateScanValueCalib(xoap::MessageReference msg);
-
-        protected:
-            class OptoHybridInfo {
-            public:
-                OptoHybridInfo();
-                void registerFields(xdata::Bag<OptoHybridManager::OptoHybridInfo>* bag);
-
-                xdata::Boolean present; ///< FIXME BAD USAGE
-                xdata::Integer crateID; ///< Specifies the crate to which the OptoHybrid is connected
-                xdata::Integer slotID; ///< Specifies the AMC slot to which the OptoHybrid is connected
-                xdata::Integer linkID; ///< Specifies the AMC link to which the OptoHybrid is connected
-
-                inline std::string toString()
-                {
-                    std::stringstream os;
-                    os << "present:" << present.toString() << std::endl
-                       << "crateID:" << crateID.toString() << std::endl
-                       << "slotID:" << slotID.toString() << std::endl
-                       << "linkID:" << linkID.toString() << std::endl
-                       << std::endl;
-                    return os.str();
-                };
-            };
-
-        private:
-            mutable gem::utils::Lock m_deviceLock; ///< [MAX_OPTOHYBRIDS_PER_AMC*MAX_AMCS_PER_CRATE];
-
-            /// @brief Template container that contains a matrix of elements of some type
-            /// @tparam T the type of object in the collection
-            /// @tparam N First dimension of the matrix
-            /// @tparam M Second dimension of the matrix
-            template <class T, size_t N, size_t M>
-            using HWMapMatrix = std::array<std::array<T, N>, M>;
-
-            HWMapMatrix<optohybrid_shared_ptr, MAX_OPTOHYBRIDS_PER_AMC, MAX_AMCS_PER_CRATE>
-                m_optohybrids; ///< HwOptoHybrid pointers to be managed
-
-            HWMapMatrix<is_toolbox_ptr, MAX_OPTOHYBRIDS_PER_AMC, MAX_AMCS_PER_CRATE>
-                is_optohybrids; ///< OptoHybrid InfoSpace pointers to be managed
-
-            xdata::Vector<xdata::Bag<OptoHybridInfo>> m_optohybridInfo; ///<
-
-            HWMapMatrix<uint32_t, MAX_OPTOHYBRIDS_PER_AMC, MAX_AMCS_PER_CRATE>
-                m_broadcastList; ///< VFAT slots to block slow control broadcasts
-
-            uint32_t m_lastLatency; ///< Special variable for latency scan mode
-            uint32_t m_lastVT1, m_lastVT2; ///< Special variable for threshold scan mode
-        }; // class OptoHybridManager
-
-    } // namespace gem::hardware::optohybrid
-} // namespace gem::hardware
-} // namespace gem
-
-#endif // GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGER_H
diff --git a/gemhardware/managers/interface/optohybrid/OptoHybridManagerWeb.h b/gemhardware/managers/interface/optohybrid/OptoHybridManagerWeb.h
deleted file mode 100644
index 52f4ca61..00000000
--- a/gemhardware/managers/interface/optohybrid/OptoHybridManagerWeb.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/// @file OptoHybridManagerWeb.h
-
-#ifndef GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGERWEB_H
-#define GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGERWEB_H
-
-#include "gem/base/GEMWebApplication.h"
-
-namespace gem {
-namespace hardware {
-    namespace optohybrid {
-
-        class OptoHybridManager;
-
-        class OptoHybridManagerWeb : public gem::base::GEMWebApplication {
-        public:
-            OptoHybridManagerWeb(OptoHybridManager* optohybridApp);
-
-            virtual ~OptoHybridManagerWeb();
-
-        protected:
-            virtual void webDefault(xgi::Input* in, xgi::Output* out);
-
-            virtual void monitorPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void expertPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void applicationPage(xgi::Input* in, xgi::Output* out);
-
-            virtual void jsonUpdate(xgi::Input* in, xgi::Output* out);
-
-            /* void boardPage(xgi::Input* in, xgi::Output* out); */
-
-        private:
-            size_t activeBoard;
-
-            //OptoHybridManagerWeb(OptoHybridManagerWeb const&);
-        };
-
-    } // namespace gem::optohybrid
-} // namespace gem::hardware
-} // namespace gem
-
-#endif // GEM_HARDWARE_OPTOHYBRID_OPTOHYBRIDMANAGERWEB_H
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index 7198e703..bb9c3a3d 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -3,8 +3,10 @@
 #include "gem/hardware/managers/AMCManager.h"
 
 #include "gem/hardware/devices/amc/HwGenericAMC.h"
+#include "gem/hardware/devices/optohybrid/HwOptoHybrid.h"
 #include "gem/hardware/managers/AMCManagerWeb.h"
 #include "gem/hardware/managers/exception/Exception.h"
+#include "gem/hardware/managers/optohybrid/exception/Exception.h"
 #include "gem/hardware/utils/GEMCrateUtils.h"
 
 #include "xoap/AttachmentPart.h"
@@ -27,19 +29,23 @@ gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
 
     p_appInfoSpace->fireItemAvailable("crate", &m_crate);
     p_appInfoSpace->fireItemAvailable("slot", &m_slot);
+    p_appInfoSpace->fireItemAvailable("optohybridMask", &m_optohybridMask);
     p_appInfoSpace->fireItemAvailable("enableZS", &m_enableZS);
 
     p_appInfoSpace->addItemRetrieveListener("crate", this);
     p_appInfoSpace->addItemRetrieveListener("slot", this);
+    p_appInfoSpace->addItemRetrieveListener("optohybridMask", this);
     p_appInfoSpace->addItemRetrieveListener("enableZS", this);
 
     p_appInfoSpace->addItemChangedListener("crate", this);
     p_appInfoSpace->addItemChangedListener("slot", this);
+    p_appInfoSpace->addItemChangedListener("optohybridMask", this);
     p_appInfoSpace->addItemChangedListener("enableZS", this);
 
     xoap::bind<gem::base::GEMApplication>(this, &gem::base::GEMApplication::calibParamRetrieve, "calibParamRetrieve", XDAQ_NS_URI);
     xoap::bind(this, &gem::hardware::AMCManager::setRunTypeInterCalib, "setRunTypeInterCalib", XDAQ_NS_URI);
     xoap::bind(this, &gem::hardware::AMCManager::updateRunParamCalib, "updateRunParamCalib", XDAQ_NS_URI);
+    xoap::bind(this, &gem::hardware::AMCManager::updateScanValueCalib, "updateScanValueCalib", XDAQ_NS_URI);
 
     init();
 }
@@ -67,13 +73,25 @@ void gem::hardware::AMCManager::initializeAction()
 {
     CMSGEMOS_INFO("AMCManager::initializeAction begin");
 
-    std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_);
-
+    // == AMC ==
+    const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d", m_crate.value_, m_slot.value_);
     try {
         m_amc = std::make_shared<gem::hardware::amc::HwGenericAMC>(deviceName);
     }
     GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
 
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        const std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d-optohybrid%02d", m_crate.value_, m_slot.value_, link);
+        try {
+            m_optohybrids.at(link) = std::make_shared<gem::hardware::optohybrid::HwOptoHybrid>(deviceName);
+        }
+        GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
+    }
+
     CMSGEMOS_INFO("AMCManager::initializeAction end");
 }
 
@@ -81,30 +99,34 @@ void gem::hardware::AMCManager::configureAction()
 {
     CMSGEMOS_INFO("AMCManager::configureAction begin");
 
+    // == AMC ==
+
     // Recover AMC: check clocks, reload AMC FW, restart RPC sevice
+    CMSGEMOS_INFO("AMCManager::configureAction: recover AMC");
     m_amc->recoverAMC();
 
     if (!m_amc->isHwConnected()) {
-        std::stringstream msg;
-        msg << "AMCManager::configureAction AMC in slot " << m_slot.value_ << " is not connected";
-        CMSGEMOS_ERROR(msg.str());
-        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
+        std::stringstream errmsg;
+        errmsg << "AMCManager::configureAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(errmsg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
     }
 
-    CMSGEMOS_INFO("AMCManager::configureAction: establish front end communication");
+    CMSGEMOS_INFO("AMCManager::configureAction: establish front-end communication");
     try {
         m_amc->establishFrontEndCommunication();
     }
     GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
+    CMSGEMOS_INFO("AMCManager::configureAction: configure DAQ module");
     const bool inputEnableMask = m_amc->connectedLinks();
     try {
         m_amc->configureDAQModule(inputEnableMask, m_enableZS.value_);
     }
     GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
+    // Calibration
     if (m_scanInfo.bag.scanType.value_ == 2) {
-
         m_amc->setDAQLinkRunType(0x2);
         uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (m_scanInfo.bag.scanMin.value_ & 0x3ff));
         //                       isExtTrig; isCurrentPulse; CFG_CAL_DAC;   MSPL/\;
@@ -132,7 +154,75 @@ void gem::hardware::AMCManager::configureAction()
         // m_amc->setDAQLinkRunParameter(0x1,latency);  // set this at start so DQM has it?
         m_amc->setDAQLinkRunParameter(0x2, initialVT1);
         m_amc->setDAQLinkRunParameter(0x3, initialVT2);
-    } else {
+    }
+
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        auto&& optohybrid = m_optohybrids.at(link);
+
+        if (!optohybrid->isHwConnected()) {
+            std::stringstream errmsg;
+            errmsg << "AMCManager::configureAction: OptoHybrid connected on link " << link << " to AMC in slot " << m_slot.value_ << " is not responding";
+            CMSGEMOS_ERROR(errmsg.str());
+            XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
+        }
+
+        // First of all, update the connected VFAT list
+        // Since front-end access is forbiden in the initialization step,
+        // this is the only place where it can be done while waiting for the DB
+        m_vfatMask.at(link) = ~(optohybrid->getConnectedVFATMask(true));
+        const uint32_t vfatMask = m_vfatMask.at(link);
+
+        CMSGEMOS_INFO("AMCManager::configureAction: configure VFATs");
+        optohybrid->configureVFATs();
+
+        // Calibration
+        if (m_scanInfo.bag.scanType.value_ == 2) {
+            //TODO:set calibration mode (atm set to false)
+            if (m_scanInfo.bag.calMode.value_)
+                optohybrid->configureOHCalDataFormat(vfatMask);
+
+            CMSGEMOS_DEBUG("AMCManager::configureAction configureAction: Latency scan with value " << m_scanInfo.bag.scanMin.value_);
+            optohybrid->broadcastWrite("CFG_LATENCY", m_scanInfo.bag.scanMin.value_, vfatMask, false);
+            optohybrid->broadcastWrite("CFG_PULSE_STRETCH", m_scanInfo.bag.mspl.value_, vfatMask, false);
+
+            if (m_scanInfo.bag.signalSourceType.value_ < 1) { //CG: Cal pulse
+                optohybrid->broadcastWrite("CFG_CAL_MODE", 0x1, vfatMask, false);
+            } ///for latency scans use the Voltage pulse(CAL_MODE 0x1), low CFG_CAL_DAC is a high injected charge amount
+            optohybrid->broadcastWrite("CFG_CAL_DAC", 6, vfatMask, false);
+            CMSGEMOS_DEBUG("AMCManager::configureAction: reading  specifics for latency on OH0VFAT23 MPSL " << m_scanInfo.bag.mspl.value_ << " reg " << optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_PULSE_STRETCH") << " CAL_DAC " << (uint32_t)optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_CAL_DAC"));
+
+            // enabling and disabling calpulse for channels on vfat
+            for (int ch = 0; ch < 128; ++ch) {
+                char reg[100];
+                if (ch < m_scanInfo.bag.vfatChMin.value_ || ch > m_scanInfo.bag.vfatChMax.value_) {
+                    sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
+                    optohybrid->broadcastWrite(reg, 0, vfatMask, false);
+                } else {
+                    sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
+                    optohybrid->broadcastWrite(reg, 1, vfatMask, false);
+                }
+            }
+
+            CMSGEMOS_INFO("AMCManager::configureAction: ending  specifics for latency ");
+
+        } else if (m_scanInfo.bag.scanType.value_ == 3) { //S-curve
+            // FIXME OBSOLETE
+
+            optohybrid->broadcastWrite("CFG_LATENCY", m_scanInfo.bag.latency.value_, vfatMask, false);
+            optohybrid->broadcastWrite("CFG_PULSE_STRETCH", m_scanInfo.bag.mspl.value_, vfatMask, false);
+            optohybrid->broadcastWrite("CFG_CAL_PHI", m_scanInfo.bag.pulseDelay.value_, vfatMask, false);
+            ///for Scurve scans use Current pulse, high CFG_CAL_DAC is a high injected charge amount
+            int caldac = 250;
+            optohybrid->broadcastWrite("CFG_CAL_DAC", caldac, vfatMask, false);
+
+            uint32_t initialVT1 = m_scanInfo.bag.scanMin.value_; //m_scanMin.value_;
+
+            uint32_t initialVT2 = 0; //std::max(0,(uint32_t)m_scanMax.value_);
+        }
     }
 
     CMSGEMOS_INFO("AMCManager::configureAction end");
@@ -142,6 +232,7 @@ void gem::hardware::AMCManager::startAction()
 {
     CMSGEMOS_INFO("AMCManager::startAction begin");
 
+    // == Set calibration parameters ==
     if (m_scanInfo.bag.scanType.value_ == 2) {
         CMSGEMOS_INFO("AMCManager::startAction() " << std::endl
                                                    << m_scanInfo.bag.toString());
@@ -154,25 +245,44 @@ void gem::hardware::AMCManager::startAction()
         m_lastVT1 = m_scanInfo.bag.scanMin.value_;
     }
 
-    if (m_amc->isHwConnected()) {
-        CMSGEMOS_DEBUG("connected a card in slot " << m_slot.value_);
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        auto&& optohybrid = m_optohybrids.at(link);
 
-        //FIXME shall be one RPC call?
-        m_amc->ttcModuleReset();
+        if (!optohybrid->isHwConnected()) {
+            std::stringstream errmsg;
+            errmsg << "AMCManager::startAction: OptoHybrid connected on link " << link << " to AMC in slot " << m_slot.value_ << " is not responding";
+            CMSGEMOS_ERROR(errmsg.str());
+            XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
+        }
 
-        // This is the most sensible order
-        // 1. Reset, 2. Activation, 3. Start
-        m_amc->resetDAQLink();
-        m_amc->enableDAQLink();
-        m_amc->setL1AEnable(true);
+        // Work from "front-end" to "back-end"
+        // I.e. VFAT first then OptoHybrid FPGA
+        const uint32_t vfatMask = m_vfatMask.at(link);
+        optohybrid->broadcastWrite("CFG_RUN", 0x1, vfatMask);
 
-    } else {
-        std::stringstream msg;
-        msg << "AMCManager::startAction AMC in slot " << m_slot.value_ << " is not connected";
-        CMSGEMOS_ERROR(msg.str());
-        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
+        optohybrid->counterReset();
     }
 
+    // == AMC ==
+    if (!m_amc->isHwConnected()) {
+        std::stringstream errmsg;
+        errmsg << "AMCManager::startAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(errmsg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
+    }
+
+    m_amc->ttcModuleReset();
+
+    // This is the most sensible order
+    // 1. Reset, 2. Activation, 3. Start
+    m_amc->resetDAQLink();
+    m_amc->enableDAQLink();
+    m_amc->setL1AEnable(true);
+
     CMSGEMOS_INFO("AMCManager::startAction end");
 }
 
@@ -180,47 +290,54 @@ void gem::hardware::AMCManager::pauseAction()
 {
     CMSGEMOS_INFO("AMCManager::pauseAction begin");
 
-    if (m_amc->isHwConnected()) {
-        CMSGEMOS_DEBUG("connected a card in slot " << m_slot.value_);
-
-        if (m_scanInfo.bag.scanType.value_ == 2) {
-            uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
-            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan AMC" << m_slot.value_ << " Latency " << (int)updatedLatency);
+    // == AMC ==
+    if (!m_amc->isHwConnected()) {
+        std::stringstream errmsg;
+        errmsg << "AMCManager::pauseAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(errmsg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
+    }
 
-            // wait for events to finish building
-            while (!m_amc->l1aFIFOIsEmpty()) {
-                CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
-                usleep(10);
-            }
-            CMSGEMOS_DEBUG("AMCManager::pauseAction AMC" << m_slot.value_ << " finished building events, updating run parameter "
-                                                         << (int)updatedLatency);
-            m_amc->setDAQLinkRunParameter(0x1, updatedLatency);
-        } else if (m_scanInfo.bag.scanType.value_ == 3) {
-            uint8_t updatedVT1 = m_lastVT1 + m_stepSize.value_;
-            uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
-            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan AMC" << m_slot.value_ << ""
-                                                                      << " VT1 " << (int)updatedVT1
-                                                                      << " VT2 " << (int)updatedVT2);
+    // Calibration
+    if (m_scanInfo.bag.scanType.value_ == 2) {
+        uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
+        CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan AMC" << m_slot.value_ << " Latency " << (int)updatedLatency);
 
-            // wait for events to finish building
-            while (!m_amc->l1aFIFOIsEmpty()) {
-                CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
-                usleep(10);
-            }
-            CMSGEMOS_DEBUG("AMCManager::pauseAction finished AMC" << m_slot.value_ << " building events, updating VT1 " << (int)updatedVT1
-                                                                  << " and VT2 " << (int)updatedVT2);
-            m_amc->setDAQLinkRunParameter(0x2, updatedVT1);
-            m_amc->setDAQLinkRunParameter(0x3, updatedVT2);
+        // wait for events to finish building
+        while (!m_amc->l1aFIFOIsEmpty()) {
+            CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
+            usleep(10);
+        }
+        CMSGEMOS_DEBUG("AMCManager::pauseAction AMC" << m_slot.value_ << " finished building events, updating run parameter "
+                                                     << (int)updatedLatency);
+        m_amc->setDAQLinkRunParameter(0x1, updatedLatency);
+    } else if (m_scanInfo.bag.scanType.value_ == 3) {
+        uint8_t updatedVT1 = m_lastVT1 + m_stepSize.value_;
+        uint8_t updatedVT2 = 0; //std::max(0,(int)m_scanInfo.bag.scanMax.value_);
+        CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan AMC" << m_slot.value_ << ""
+                                                                  << " VT1 " << (int)updatedVT1
+                                                                  << " VT2 " << (int)updatedVT2);
+
+        // wait for events to finish building
+        while (!m_amc->l1aFIFOIsEmpty()) {
+            CMSGEMOS_DEBUG("AMCManager::pauseAction waiting for AMC" << m_slot.value_ << " to finish building events");
+            usleep(10);
         }
+        CMSGEMOS_DEBUG("AMCManager::pauseAction finished AMC" << m_slot.value_ << " building events, updating VT1 " << (int)updatedVT1
+                                                              << " and VT2 " << (int)updatedVT2);
+        m_amc->setDAQLinkRunParameter(0x2, updatedVT1);
+        m_amc->setDAQLinkRunParameter(0x3, updatedVT2);
+    }
+
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
 
-    } else {
-        std::stringstream msg;
-        msg << "AMCManager::pauseAction AMC in slot " << m_slot.value_ << " is not connected";
-        CMSGEMOS_ERROR(msg.str());
-        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg.str());
+        auto&& optohybrid = m_optohybrids.at(link);
     }
 
-    // Update the scan parameters
+    // == Update the scan parameters ==
     if (m_scanInfo.bag.scanType.value_ == 2) {
         CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan old Latency " << (int)m_lastLatency);
         m_lastLatency += m_stepSize.value_;
@@ -238,6 +355,16 @@ void gem::hardware::AMCManager::resumeAction()
 {
     CMSGEMOS_INFO("AMCManager::resumeAction begin");
 
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        auto&& optohybrid = m_optohybrids.at(link);
+    }
+
+    // == AMC ==
+
     CMSGEMOS_INFO("AMCManager::resumeAction end");
 }
 
@@ -245,12 +372,36 @@ void gem::hardware::AMCManager::stopAction()
 {
     CMSGEMOS_INFO("AMCManager::stopAction begin");
 
-    if (m_amc->isHwConnected()) {
-        m_amc->setL1AEnable(false);
-        m_amc->disableDAQLink();
-        m_amc->resetDAQLink();
+    // == OptoHybrid ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        auto&& optohybrid = m_optohybrids.at(link);
+
+        if (!optohybrid->isHwConnected()) {
+            std::stringstream errmsg;
+            errmsg << "AMCManager::stopAction: OptoHybrid connected on link " << link << " to AMC in slot " << m_slot.value_ << " is not responding";
+            CMSGEMOS_ERROR(errmsg.str());
+            XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
+        }
+
+        const uint32_t vfatMask = m_vfatMask.at(link);
+        optohybrid->broadcastWrite("CFG_RUN", 0x0, vfatMask);
     }
 
+    // == AMC ==
+    if (!m_amc->isHwConnected()) {
+        std::stringstream errmsg;
+        errmsg << "AMCManager::stopAction AMC in slot " << m_slot.value_ << " is not connected";
+        CMSGEMOS_ERROR(errmsg.str());
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
+    }
+
+    m_amc->setL1AEnable(false);
+    m_amc->disableDAQLink();
+    m_amc->resetDAQLink();
+
     CMSGEMOS_INFO("AMCManager::stopAction end");
 }
 
@@ -258,10 +409,16 @@ void gem::hardware::AMCManager::haltAction()
 {
     CMSGEMOS_INFO("AMCManager::haltAction begin");
 
-    if (m_amc->isHwConnected()) {
-        m_amc->setL1AEnable(false);
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
+
+        auto&& optohybrid = m_optohybrids.at(link);
     }
 
+    // == AMC ==
+
     CMSGEMOS_INFO("AMCManager::haltAction end");
 }
 
@@ -269,11 +426,15 @@ void gem::hardware::AMCManager::resetAction()
 {
     CMSGEMOS_INFO("AMCManager::resetAction begin");
 
-    if (m_amc->isHwConnected()) {
-        m_amc->setL1AEnable(false);
-    }
+    // == AMC ==
+
+    // == OptoHybrids ==
+    for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+        if (!((m_optohybridMask.value_ >> link) & 0x1))
+            continue;
 
-    CMSGEMOS_DEBUG("AMCManager::looking for hwCfgInfoSpace items for AMC in slot " << m_slot.value_);
+        auto&& optohybrid = m_optohybrids.at(link);
+    }
 
     CMSGEMOS_INFO("AMCManager::resetAction end");
 }
@@ -380,3 +541,66 @@ xoap::MessageReference gem::hardware::AMCManager::updateRunParamCalib(xoap::Mess
     XCEPT_RAISE(xoap::exception::Exception, "command not found");
     return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "NotDone");
 }
+
+xoap::MessageReference gem::hardware::AMCManager::updateScanValueCalib(xoap::MessageReference msg)
+{
+    std::string commandName = "updateScanValueCalib";
+    CMSGEMOS_DEBUG("AMCManager::updateScanValueCalib");
+    try {
+        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
+            if (!((m_optohybridMask.value_ >> link) & 0x1))
+                continue;
+
+            auto&& optohybrid = m_optohybrids.at(link);
+
+            if (optohybrid->isHwConnected()) {
+                // turn on all VFATs? or should they always be on?
+                const uint32_t vfatMask = m_vfatMask.at(link);
+                if (m_scanInfo.bag.scanType.value_ == 2) {
+                    uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
+                    CMSGEMOS_DEBUG("AMCManager::updateScanValueCalib LatencyScan OptoHybrid on link " << static_cast<uint32_t>(link)
+                                                                                                      << " AMC slot " << m_slot.value_ << " Latency  " << static_cast<uint32_t>(updatedLatency));
+
+                    optohybrid->broadcastWrite("CFG_LATENCY", updatedLatency, vfatMask);
+                } else if (m_scanInfo.bag.scanType.value_ == 3) { // FIXME OBSOLETE
+                    uint8_t updatedVT1 = m_lastVT1 + m_scanInfo.bag.stepSize.value_;
+                    uint8_t VT2 = 0; // std::max(0,static_cast<uint32_t>(m_scanMax.value_));
+                    CMSGEMOS_INFO("AMCManager::ThresholdScan OptoHybrid on link " << static_cast<uint32_t>(link)
+                                                                                  << " AMC slot " << m_slot.value_ << " VT1 " << static_cast<uint32_t>(updatedVT1)
+                                                                                  << " VT2 " << VT2 << " StepSize " << m_scanInfo.bag.stepSize.value_);
+
+                    // optohybrid->broadcastWrite("CFG_THR_ARM_DAC", updatedVT1, vfatMask);
+                    // optohybrid->broadcastWrite("CFG_THR_ZCC_DAC", VT2, vfatMask);
+                }
+                // what resets to do
+            } else {
+                std::stringstream errmsg;
+                errmsg << "AMCManager::updateScanValueCalib OptoHybrid connected on link " << static_cast<uint32_t>(link)
+                       << " to AMC in slot " << m_slot.value_ << " is not responding";
+                CMSGEMOS_ERROR(errmsg.str());
+                // fireEvent("Fail");
+                XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
+            }
+        }
+
+        // Update the scan parameters
+        if (m_scanInfo.bag.scanType.value_ == 2) {
+            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan old Latency " << static_cast<uint32_t>(m_lastLatency));
+            m_lastLatency += m_scanInfo.bag.stepSize.value_;
+            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan new Latency " << static_cast<uint32_t>(m_lastLatency));
+        } else if (m_scanInfo.bag.scanType.value_ == 3) {
+            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan old VT1 " << static_cast<uint32_t>(m_lastVT1));
+            m_lastVT1 += m_scanInfo.bag.stepSize.value_;
+            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan new VT1 " << static_cast<uint32_t>(m_lastVT1));
+        }
+        CMSGEMOS_INFO("AMCManager::updateScanValueCalib end");
+
+        return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "Done");
+
+    } catch (xcept::Exception& err) {
+        std::string msgBase = toolbox::toString("Failed to create SOAP reply for command '%s'",
+            commandName.c_str());
+        CMSGEMOS_ERROR(toolbox::toString("%s: %s.", msgBase.c_str(), xcept::stdformat_exception_history(err).c_str()));
+    }
+    return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "NotDone");
+}
diff --git a/gemhardware/managers/src/AMCManagerWeb.cpp b/gemhardware/managers/src/AMCManagerWeb.cpp
index 0d851067..f688420b 100644
--- a/gemhardware/managers/src/AMCManagerWeb.cpp
+++ b/gemhardware/managers/src/AMCManagerWeb.cpp
@@ -12,29 +12,33 @@
 gem::hardware::AMCManagerWeb::AMCManagerWeb(gem::hardware::AMCManager* amcApp)
     : gem::base::GEMWebApplication(amcApp)
 {
-    // default constructor
 }
 
 gem::hardware::AMCManagerWeb::~AMCManagerWeb()
 {
-    // default destructor
 }
 
 void gem::hardware::AMCManagerWeb::webDefault(xgi::Input* in, xgi::Output* out)
 {
     if (p_gemFSMApp)
         CMSGEMOS_DEBUG("current state is" << dynamic_cast<gem::hardware::AMCManager*>(p_gemFSMApp)->getCurrentState());
+
+    *out << cgicc::style().set("type", "text/css").set("src", "/gemdaq/gemhardware/html/css/optohybrid/optohybrid.css")
+         << cgicc::style() << std::endl;
+
     *out << cgicc::script().set("type", "text/javascript").set("src", "/gemdaq/gemhardware/html/scripts/amc/amc.js")
          << cgicc::script() << std::endl;
 
+    *out << cgicc::script().set("type", "text/javascript").set("src", "/gemdaq/gemhardware/html/scripts/optohybrid/optohybrid.js")
+         << cgicc::script() << std::endl;
+
     GEMWebApplication::webDefault(in, out);
 }
 
-/*To be filled in with the expert page code*/
 void gem::hardware::AMCManagerWeb::expertPage(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::expertPage");
-    // fill this page with the expert views for the AMCManager
+
     *out << "    <div class=\"xdaq-tab-wrapper\">" << std::endl;
     *out << "      <div class=\"xdaq-tab\" title=\"Register dump page\"/>" << std::endl;
     registerDumpPage(in, out);
@@ -42,7 +46,6 @@ void gem::hardware::AMCManagerWeb::expertPage(xgi::Input* in, xgi::Output* out)
     *out << "    </div>" << std::endl;
 }
 
-/*To be filled in with the application page code*/
 void gem::hardware::AMCManagerWeb::applicationPage(xgi::Input* in, xgi::Output* out)
 {
     std::string cardURL = "/" + p_gemApp->getApplicationDescriptor()->getURN() + "/cardPage";
@@ -51,11 +54,9 @@ void gem::hardware::AMCManagerWeb::applicationPage(xgi::Input* in, xgi::Output*
     *out << "  </div>" << std::endl;
 }
 
-/*To be filled in with the card page code*/
 void gem::hardware::AMCManagerWeb::registerDumpPage(xgi::Input* in, xgi::Output* out)
 {
     CMSGEMOS_DEBUG("AMCManagerWeb::registerDumpPage");
-    // dump registers for a given AMC and display
 }
 
 void gem::hardware::AMCManagerWeb::monitorPage(xgi::Input* in, xgi::Output* out)
diff --git a/gemhardware/managers/src/optohybrid/OptoHybridManager.cpp b/gemhardware/managers/src/optohybrid/OptoHybridManager.cpp
deleted file mode 100644
index a999099e..00000000
--- a/gemhardware/managers/src/optohybrid/OptoHybridManager.cpp
+++ /dev/null
@@ -1,460 +0,0 @@
-/// class: OptoHybridManager
-/// description: Manager application for OptoHybrid cards
-///              structure borrowed from TCDS core, with nods to HCAL and EMU code
-/// author: J. Sturdy
-/// date:
-
-#include "gem/hardware/managers/optohybrid/OptoHybridManager.h"
-
-#include "gem/hardware/devices/optohybrid/HwOptoHybrid.h"
-#include "gem/hardware/managers/optohybrid/OptoHybridManagerWeb.h"
-
-#include "gem/hardware/devices/exception/Exception.h"
-#include "gem/hardware/managers/exception/Exception.h"
-#include "gem/hardware/managers/optohybrid/exception/Exception.h"
-#include "gem/utils/exception/Exception.h"
-
-#include "gem/hardware/utils/GEMCrateUtils.h"
-
-#include "xoap/AttachmentPart.h"
-#include "xoap/MessageFactory.h"
-#include "xoap/MessageReference.h"
-#include "xoap/Method.h"
-#include "xoap/SOAPBody.h"
-#include "xoap/SOAPConstants.h"
-#include "xoap/SOAPEnvelope.h"
-#include "xoap/domutils.h"
-
-XDAQ_INSTANTIATOR_IMPL(gem::hardware::optohybrid::OptoHybridManager);
-
-gem::hardware::optohybrid::OptoHybridManager::OptoHybridInfo::OptoHybridInfo()
-{
-    present = false;
-    crateID = -1;
-    slotID = -1;
-    linkID = -1;
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::OptoHybridInfo::registerFields(xdata::Bag<gem::hardware::optohybrid::OptoHybridManager::OptoHybridInfo>* bag)
-{
-    bag->addField("crateID", &crateID);
-    bag->addField("slot", &slotID);
-    bag->addField("link", &linkID);
-    bag->addField("present", &present);
-}
-
-gem::hardware::optohybrid::OptoHybridManager::OptoHybridManager(xdaq::ApplicationStub* stub)
-    : gem::base::GEMFSMApplication(stub)
-{
-    m_optohybridInfo.setSize(MAX_OPTOHYBRIDS_PER_AMC * MAX_AMCS_PER_CRATE);
-
-    p_appInfoSpace->fireItemAvailable("AllOptoHybridsInfo", &m_optohybridInfo);
-
-    p_appInfoSpace->addItemRetrieveListener("AllOptoHybridsInfo", this);
-    p_appInfoSpace->addItemChangedListener("AllOptoHybridsInfo", this);
-
-    // initialize the OptoHybrid application objects
-    CMSGEMOS_DEBUG("OptoHybridManager::Connecting to the OptoHybridManagerWeb interface");
-    p_gemWebInterface = new gem::hardware::optohybrid::OptoHybridManagerWeb(this);
-    CMSGEMOS_DEBUG("OptoHybridManager::done");
-    xoap::bind(this, &gem::hardware::optohybrid::OptoHybridManager::updateScanValueCalib, "updateScanValueCalib", XDAQ_NS_URI);
-    // set up the info hwCfgInfoSpace
-    init();
-}
-
-gem::hardware::optohybrid::OptoHybridManager::~OptoHybridManager()
-{
-    // memory management, maybe not necessary here?
-}
-
-// This is the callback used for handling xdata:Event objects
-void gem::hardware::optohybrid::OptoHybridManager::actionPerformed(xdata::Event& event)
-{
-    if (event.type() == "setDefaultValues" || event.type() == "urn:xdaq-event:setDefaultValues") {
-        CMSGEMOS_DEBUG("OptoHybridManager::actionPerformed() setDefaultValues"
-            << "Default configuration values have been loaded from xml profile");
-
-        // how to handle passing in various values nested in a vector in a bag
-        for (auto& board : m_optohybridInfo) {
-            // if (board->bag.present.value_) {
-            auto& cfgbag = board.bag;
-            if (cfgbag.crateID.value_ > -1) {
-                cfgbag.present = true;
-                CMSGEMOS_INFO("OptoHybridManager::Found attribute:" << cfgbag.toString());
-            }
-        }
-    }
-    // update monitoring variables
-    gem::base::GEMApplication::actionPerformed(event);
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::init()
-{
-}
-
-// state transitions
-void gem::hardware::optohybrid::OptoHybridManager::initializeAction()
-{
-    CMSGEMOS_DEBUG("OptoHybridManager::initializeAction begin");
-    // FIXME make me more streamlined
-    for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        CMSGEMOS_DEBUG("OptoHybridManager::initializeAction looping over slots("
-            << (slot + 1) << ") and finding expected cards");
-        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-            CMSGEMOS_DEBUG("OptoHybridManager::initializeAction looping over links("
-                << link << ") and finding expected cards");
-            size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-            CMSGEMOS_DEBUG("OptoHybridManager::initializeAction index = " << index);
-            OptoHybridInfo& info = m_optohybridInfo[index].bag;
-            CMSGEMOS_DEBUG("OptoHybridManager::initializeAction bag"
-                << "crate " << info.crateID.value_
-                << " slot " << info.slotID.value_
-                << " link " << info.linkID.value_);
-
-            if (!info.present)
-                continue;
-
-            CMSGEMOS_DEBUG("OptoHybridManager::initializeAction: info is: " << info.toString());
-            CMSGEMOS_DEBUG("OptoHybridManager::initializeAction creating pointer to board connected on link "
-                << link << " to AMC in slot " << (slot + 1));
-            std::string deviceName = toolbox::toString("gem-shelf%02d-amc%02d-optohybrid%02d",
-                info.crateID.value_,
-                info.slotID.value_,
-                info.linkID.value_);
-
-            toolbox::net::URN hwCfgURN("urn:gem:hw:" + deviceName);
-
-            if (xdata::getInfoSpaceFactory()->hasItem(hwCfgURN.toString())) {
-                CMSGEMOS_DEBUG("OptoHybridManager::initializeAction::infospace "
-                    << hwCfgURN.toString() << " already exists, getting");
-                is_optohybrids.at(slot).at(link) = std::make_shared<gem::base::utils::GEMInfoSpaceToolBox>(this,
-                    hwCfgURN.toString(),
-                    true);
-
-            } else {
-                CMSGEMOS_DEBUG("OptoHybridManager::initializeAction::infospace "
-                    << hwCfgURN.toString() << " does not exist, creating");
-                is_optohybrids.at(slot).at(link) = std::make_shared<gem::base::utils::GEMInfoSpaceToolBox>(this,
-                    hwCfgURN.toString(),
-                    true);
-            }
-
-            try {
-                CMSGEMOS_DEBUG("OptoHybridManager::initializeAction obtaining pointer to HwOptoHybrid " << deviceName
-                                                                                                        << " (slot " << slot + 1 << ")"
-                                                                                                        << " (link " << link << ")");
-                m_optohybrids.at(slot).at(link) = std::make_shared<gem::hardware::optohybrid::HwOptoHybrid>(deviceName);
-                auto&& optohybrid = m_optohybrids.at(slot).at(link);
-            }
-            GEM_HARDWARE_TRANSITION_CATCH("OptoHybridManager::initializeAction", gem::hardware::devices::exception::Exception);
-            // set the web view to be empty or grey
-            // if (!info.present.value_) continue;
-            // p_gemWebInterface->optohybridInSlot(slot);
-        }
-    }
-    CMSGEMOS_INFO("OptoHybridManager::initializeAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::configureAction()
-{
-    CMSGEMOS_DEBUG("OptoHybridManager::configureAction");
-    // FIXME make me more streamlined
-    for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-            size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-            CMSGEMOS_DEBUG("OptoHybridManager::index = " << index);
-            OptoHybridInfo& info = m_optohybridInfo[index].bag;
-
-            CMSGEMOS_DEBUG("OptoHybridManager::configureAction::info is: " << info.toString());
-            if (!info.present)
-                continue;
-
-            CMSGEMOS_DEBUG("OptoHybridManager::configureAction::grabbing pointer to hardware device");
-            auto&& optohybrid = m_optohybrids.at(slot).at(link);
-
-            if (optohybrid->isHwConnected()) {
-                // First of all, update the connected VFAT list
-                // Since front-end access is forbiden in the initialization step,
-                // this is the only place where it can be done while waiting for the DB
-                m_broadcastList.at(slot).at(link) = ~(optohybrid->getConnectedVFATMask(true));
-                const uint32_t vfatMask = m_broadcastList.at(slot).at(link);
-
-                CMSGEMOS_INFO("OptoHybridManager::configureAction:: configuring VFATs");
-                optohybrid->configureVFATs();
-
-                if (m_scanInfo.bag.scanType.value_ == 2) {
-                    //TODO:set calibration mode (atm set to false)
-                    if (m_scanInfo.bag.calMode.value_)
-                        optohybrid->configureOHCalDataFormat(vfatMask);
-
-                    CMSGEMOS_DEBUG("OptoHybridManager::configureAction configureAction: Latency scan with value " << m_scanInfo.bag.scanMin.value_);
-                    optohybrid->broadcastWrite("CFG_LATENCY", m_scanInfo.bag.scanMin.value_, vfatMask, false);
-                    optohybrid->broadcastWrite("CFG_PULSE_STRETCH", m_scanInfo.bag.mspl.value_, vfatMask, false);
-
-                    if (m_scanInfo.bag.signalSourceType.value_ < 1) { //CG: Cal pulse
-                        optohybrid->broadcastWrite("CFG_CAL_MODE", 0x1, vfatMask, false);
-                    } ///for latency scans use the Voltage pulse(CAL_MODE 0x1), low CFG_CAL_DAC is a high injected charge amount
-                    optohybrid->broadcastWrite("CFG_CAL_DAC", 6, vfatMask, false);
-                    CMSGEMOS_DEBUG("OptoHybridManager::configureAction: reading  specifics for latency on OH0VFAT23 MPSL " << m_scanInfo.bag.mspl.value_ << " reg " << optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_PULSE_STRETCH") << " CAL_DAC " << (uint32_t)optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_CAL_DAC"));
-
-                    // enabling and disabling calpulse for channels on vfat
-                    for (int ch = 0; ch < 128; ++ch) {
-                        char reg[100];
-                        if (ch < m_scanInfo.bag.vfatChMin.value_ || ch > m_scanInfo.bag.vfatChMax.value_) {
-                            sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                            optohybrid->broadcastWrite(reg, 0, vfatMask, false);
-                        } else {
-                            sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                            optohybrid->broadcastWrite(reg, 1, vfatMask, false);
-                        }
-                    }
-
-                    CMSGEMOS_INFO("OptoHybridManager::configureAction: ending  specifics for latency ");
-
-                } else if (m_scanInfo.bag.scanType.value_ == 3) { //S-curve
-                    // FIXME OBSOLETE
-
-                    optohybrid->broadcastWrite("CFG_LATENCY", m_scanInfo.bag.latency.value_, vfatMask, false);
-                    optohybrid->broadcastWrite("CFG_PULSE_STRETCH", m_scanInfo.bag.mspl.value_, vfatMask, false);
-                    optohybrid->broadcastWrite("CFG_CAL_PHI", m_scanInfo.bag.pulseDelay.value_, vfatMask, false);
-                    ///for Scurve scans use Current pulse, high CFG_CAL_DAC is a high injected charge amount
-                    int caldac = 250;
-                    optohybrid->broadcastWrite("CFG_CAL_DAC", caldac, vfatMask, false);
-
-                    uint32_t initialVT1 = m_scanInfo.bag.scanMin.value_; //m_scanMin.value_;
-
-                    uint32_t initialVT2 = 0; //std::max(0,(uint32_t)m_scanMax.value_);
-
-                } else {
-                }
-
-                // what else is required for configuring the OptoHybrid?
-                // need to reset optical links?
-                // reset counters?
-            } else {
-                std::stringstream errmsg;
-                errmsg << "OptoHybridManager::configureAction::OptoHybrid connected on link " << static_cast<uint32_t>(link)
-                       << " to AMC in slot " << static_cast<uint32_t>(slot + 1) << " is not responding";
-                CMSGEMOS_ERROR(errmsg.str());
-                // fireEvent("Fail");
-                XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
-            }
-        }
-    }
-    CMSGEMOS_INFO("OptoHybridManager::configureAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::startAction()
-{
-
-    if (m_scanType.value_ == 2) {
-        m_lastLatency = m_scanInfo.bag.scanMin.value_;
-        m_lastVT1 = 0;
-    } else if (m_scanType.value_ == 3) {
-        m_lastLatency = 0;
-        m_lastVT1 = m_scanInfo.bag.scanMin.value_;
-    }
-
-    CMSGEMOS_DEBUG("OptoHybridManager::startAction");
-    // will the manager operate for all connected optohybrids, or only those connected to certain AMCs?
-    // FIXME make me more streamlined
-    for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-            size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-            CMSGEMOS_DEBUG("OptoHybridManager::index = " << index);
-            OptoHybridInfo& info = m_optohybridInfo[index].bag;
-            if (!info.present)
-                continue;
-
-            CMSGEMOS_DEBUG("OptoHybridManager::startAction::grabbing pointer to hardware device");
-            auto&& optohybrid = m_optohybrids.at(slot).at(link);
-
-            if (optohybrid->isHwConnected()) {
-                // Work from "front-end" to "back-end"
-                // I.e. VFAT first then OptoHybrid FPGA
-                const uint32_t vfatMask = m_broadcastList.at(slot).at(link);
-                optohybrid->broadcastWrite("CFG_RUN", 0x1, vfatMask);
-
-                // FIXME reset counters is doing nothing at the moment!
-                optohybrid->counterReset();
-            } else {
-                std::stringstream errmsg;
-                errmsg << "OptoHybridManager::startAction::OptoHybrid connected on link " << static_cast<uint32_t>(link)
-                       << " to AMC in slot " << static_cast<uint32_t>(slot + 1) << " is not responding";
-                CMSGEMOS_ERROR(errmsg.str());
-                // fireEvent("Fail");
-                XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
-            }
-        }
-    }
-    CMSGEMOS_INFO("OptoHybridManager::startAction end");
-}
-
-xoap::MessageReference gem::hardware::optohybrid::OptoHybridManager::updateScanValueCalib(xoap::MessageReference msg)
-{
-    std::string commandName = "updateScanValueCalib";
-    CMSGEMOS_DEBUG("OptohybridManager::updateScanValueCalib");
-    try {
-        CMSGEMOS_INFO("Optohybrid::updateScanValueCalib trying");
-        for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-
-            for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-                size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-
-                OptoHybridInfo& info = m_optohybridInfo[index].bag;
-
-                if (!info.present)
-                    continue;
-
-                auto&& optohybrid = m_optohybrids.at(slot).at(link);
-
-                if (optohybrid->isHwConnected()) {
-                    // turn on all VFATs? or should they always be on?
-                    uint32_t vfatMask = m_broadcastList.at(slot).at(link);
-                    if (m_scanInfo.bag.scanType.value_ == 2) {
-                        uint32_t updatedLatency = m_lastLatency + m_stepSize.value_;
-                        CMSGEMOS_DEBUG("OptoHybridManager::updateScanValueCalib LatencyScan OptoHybrid on link " << static_cast<uint32_t>(link)
-                                                                                                                 << " AMC slot " << (slot + 1) << " Latency  " << static_cast<uint32_t>(updatedLatency));
-
-                        optohybrid->broadcastWrite("CFG_LATENCY", updatedLatency, vfatMask);
-                    } else if (m_scanInfo.bag.scanType.value_ == 3) { // FIXME OBSOLETE
-                        uint8_t updatedVT1 = m_lastVT1 + m_scanInfo.bag.stepSize.value_;
-                        uint8_t VT2 = 0; // std::max(0,static_cast<uint32_t>(m_scanMax.value_));
-                        CMSGEMOS_INFO("OptoHybridManager::ThresholdScan OptoHybrid on link " << static_cast<uint32_t>(link)
-                                                                                             << " AMC slot " << (slot + 1) << " VT1 " << static_cast<uint32_t>(updatedVT1)
-                                                                                             << " VT2 " << VT2 << " StepSize " << m_scanInfo.bag.stepSize.value_);
-
-                        // optohybrid->broadcastWrite("CFG_THR_ARM_DAC", updatedVT1, vfatMask);
-                        // optohybrid->broadcastWrite("CFG_THR_ZCC_DAC", VT2, vfatMask);
-                    }
-                    // what resets to do
-                } else {
-                    std::stringstream errmsg;
-                    errmsg << "OptoHybridManager::updateScanValueCalib OptoHybrid connected on link " << static_cast<uint32_t>(link)
-                           << " to AMC in slot " << static_cast<uint32_t>(slot + 1) << " is not responding";
-                    CMSGEMOS_ERROR(errmsg.str());
-                    // fireEvent("Fail");
-                    XCEPT_RAISE(gem::hardware::managers::optohybrid::exception::Exception, errmsg.str());
-                }
-            }
-        }
-        // Update the scan parameters
-        if (m_scanInfo.bag.scanType.value_ == 2) {
-            CMSGEMOS_INFO("OptoHybridManager::pauseAction LatencyScan old Latency " << static_cast<uint32_t>(m_lastLatency));
-            m_lastLatency += m_scanInfo.bag.stepSize.value_;
-            CMSGEMOS_INFO("OptoHybridManager::pauseAction LatencyScan new Latency " << static_cast<uint32_t>(m_lastLatency));
-        } else if (m_scanInfo.bag.scanType.value_ == 3) {
-            CMSGEMOS_INFO("OptoHybridManager::pauseAction ThresholdScan old VT1 " << static_cast<uint32_t>(m_lastVT1));
-            m_lastVT1 += m_scanInfo.bag.stepSize.value_;
-            CMSGEMOS_INFO("OptoHybridManager::pauseAction ThresholdScan new VT1 " << static_cast<uint32_t>(m_lastVT1));
-        }
-        CMSGEMOS_INFO("OptoHybridManager::updateScanValueCalib end");
-
-        return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "Done");
-
-    } catch (xcept::Exception& err) {
-        std::string msgBase = toolbox::toString("Failed to create SOAP reply for command '%s'",
-            commandName.c_str());
-        CMSGEMOS_ERROR(toolbox::toString("%s: %s.", msgBase.c_str(), xcept::stdformat_exception_history(err).c_str()));
-    }
-    return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "NotDone");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::pauseAction()
-{
-
-    // FIXME put all connected VFATs into run/pause  mode?
-
-    CMSGEMOS_INFO("OptoHybridManager::pauseAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::resumeAction()
-{
-    // FIXME put all connected VFATs into run mode?
-    CMSGEMOS_INFO("OptoHybridManager::resumeAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::stopAction()
-{
-    CMSGEMOS_DEBUG("OptoHybridManager::stopAction");
-    // FIXME will the manager operate for all connected optohybrids, or only those connected to certain AMCs?
-    // FIXME TODO make me more streamlined
-    for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-
-        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-            size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-            CMSGEMOS_DEBUG("OptoHybridManager::index = " << index);
-            OptoHybridInfo& info = m_optohybridInfo[index].bag;
-
-            if (!info.present)
-                continue;
-
-            CMSGEMOS_DEBUG("OptoHybridManager::stopAction::grabbing pointer to hardware device");
-            auto&& optohybrid = m_optohybrids.at(slot).at(link);
-
-            if (optohybrid->isHwConnected()) {
-                const uint32_t vfatMask = m_broadcastList.at(slot).at(link);
-                optohybrid->broadcastWrite("CFG_RUN", 0x0, vfatMask);
-                // FIXME what resets to do
-            }
-        }
-    }
-    CMSGEMOS_INFO("OptoHybridManager::stopAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::haltAction()
-{
-    // put all connected VFATs into sleep mode?
-    usleep(10);
-    CMSGEMOS_INFO("OptoHybridManager::haltAction end");
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::resetAction()
-{
-    // unregister listeners and items in info spaces
-    CMSGEMOS_DEBUG("OptoHybridManager::resetAction begin");
-    // FIXME make me more streamlined
-    for (size_t slot = 0; slot < MAX_AMCS_PER_CRATE; ++slot) {
-        CMSGEMOS_DEBUG("OptoHybridManager::looping over slots(" << (slot + 1) << ") and finding expected cards");
-
-        for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
-            CMSGEMOS_DEBUG("OptoHybridManager::looping over links(" << link << ") and finding expected cards");
-            size_t index = (slot * MAX_OPTOHYBRIDS_PER_AMC) + link;
-            CMSGEMOS_DEBUG("OptoHybridManager::index = " << index);
-            OptoHybridInfo& info = m_optohybridInfo[index].bag;
-
-            if (!info.present)
-                continue;
-            // set up the info space here rather than in initialize (where it can then get unset in reset?
-            // should a value be set up for all of them by default?
-
-            CMSGEMOS_DEBUG("OptoHybridManager::revoking hwCfgInfoSpace items for board connected on link "
-                << link << " to AMC in slot " << (slot + 1));
-            toolbox::net::URN hwCfgURN("urn:gem:hw:" + toolbox::toString("gem-shelf%02d-amc%02d-optohybrid%02d", info.crateID.value_, info.slotID.value_, info.linkID.value_));
-            if (xdata::getInfoSpaceFactory()->hasItem(hwCfgURN.toString())) {
-                CMSGEMOS_DEBUG("OptoHybridManager::revoking config parameters into infospace");
-
-                // reset the hw infospace toolbox
-                is_optohybrids.at(slot).at(link)->reset();
-            } else {
-                CMSGEMOS_DEBUG("OptoHybridManager::resetAction::infospace " << hwCfgURN.toString() << " does not exist, no further action");
-                continue;
-            }
-        } // end loop on link < MAX_OPTOHYBRIDS_PER_AMC
-    } // end loop on slot < MAX_AMCS_PER_CRATE
-    CMSGEMOS_INFO("OptoHybridManager::resetAction end");
-}
-
-/*
-void gem::hardware::optohybrid::OptoHybridManager::noAction()
-{
-}
-*/
-
-void gem::hardware::optohybrid::OptoHybridManager::failAction(toolbox::Event::Reference e)
-{
-}
-
-void gem::hardware::optohybrid::OptoHybridManager::resetAction(toolbox::Event::Reference e)
-{
-}
diff --git a/gemhardware/managers/src/optohybrid/OptoHybridManagerWeb.cpp b/gemhardware/managers/src/optohybrid/OptoHybridManagerWeb.cpp
deleted file mode 100644
index 8b80bcbf..00000000
--- a/gemhardware/managers/src/optohybrid/OptoHybridManagerWeb.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-// OptoHybridManagerWeb.cc
-
-#include "gem/hardware/managers/optohybrid/OptoHybridManagerWeb.h"
-
-#include <iomanip>
-#include <memory>
-
-#include "xcept/tools.h"
-
-#include "gem/hardware/managers/optohybrid/OptoHybridManager.h"
-
-#include "gem/hardware/managers/optohybrid/exception/Exception.h"
-
-gem::hardware::optohybrid::OptoHybridManagerWeb::OptoHybridManagerWeb(gem::hardware::optohybrid::OptoHybridManager* optohybridApp)
-    : gem::base::GEMWebApplication(optohybridApp)
-{
-}
-
-gem::hardware::optohybrid::OptoHybridManagerWeb::~OptoHybridManagerWeb()
-{
-    //default destructor
-}
-
-void gem::hardware::optohybrid::OptoHybridManagerWeb::webDefault(xgi::Input* in, xgi::Output* out)
-{
-    if (p_gemFSMApp)
-        CMSGEMOS_DEBUG("current state is" << dynamic_cast<gem::hardware::optohybrid::OptoHybridManager*>(p_gemFSMApp)->getCurrentState());
-    *out << cgicc::style().set("type", "text/css").set("src", "/gemdaq/gemhardware/html/css/optohybrid/optohybrid.css")
-         << cgicc::style() << std::endl;
-
-    *out << cgicc::script().set("type", "text/javascript").set("src", "/gemdaq/gemhardware/html/scripts/optohybrid/optohybrid.js")
-         << cgicc::script() << std::endl;
-
-    GEMWebApplication::webDefault(in, out);
-}
-
-/*To be filled in with the expert page code*/
-void gem::hardware::optohybrid::OptoHybridManagerWeb::expertPage(xgi::Input* in, xgi::Output* out)
-{
-    CMSGEMOS_INFO("OptoHybridManagerWeb::expertPage");
-    //fill this page with the expert views for the OptoHybridManager
-    *out << "expertPage</br>" << std::endl;
-}
-
-/*To be filled in with the application page code*/
-void gem::hardware::optohybrid::OptoHybridManagerWeb::applicationPage(xgi::Input* in, xgi::Output* out)
-{
-    CMSGEMOS_INFO("OptoHybridManagerWeb::applicationPage");
-    std::string cardURL = "/" + p_gemApp->getApplicationDescriptor()->getURN() + "/boardPage";
-    *out << "  <div class=\"xdaq-tab\" title=\"Board page\"/>" << std::endl;
-    /* boardPage(in, out); */
-    *out << "  </div>" << std::endl;
-}
-
-void gem::hardware::optohybrid::OptoHybridManagerWeb::monitorPage(xgi::Input* in, xgi::Output* out)
-{
-    CMSGEMOS_DEBUG("OptoHybridManagerWeb::monitorPage");
-}
-
-void gem::hardware::optohybrid::OptoHybridManagerWeb::jsonUpdate(xgi::Input* in, xgi::Output* out)
-{
-    CMSGEMOS_DEBUG("OptoHybridManagerWeb::jsonUpdate");
-}
diff --git a/gemsupervisor/src/GEMSupervisor.cpp b/gemsupervisor/src/GEMSupervisor.cpp
index 08f0820f..0aad4714 100644
--- a/gemsupervisor/src/GEMSupervisor.cpp
+++ b/gemsupervisor/src/GEMSupervisor.cpp
@@ -1141,7 +1141,7 @@ xoap::MessageReference gem::supervisor::GEMSupervisor::EndScanPointCalib(xoap::M
                 std::set<const xdaq::ApplicationDescriptor*> allApps = ag->getApplicationDescriptors();
                 for (auto j = allApps.begin(); j != allApps.end(); ++j) {
                     std::string classname = (*j)->getClassName();
-                    if (((*j)->getClassName()).rfind("OptoHybridManager") != std::string::npos) {
+                    if (((*j)->getClassName()).rfind("AMCManager") != std::string::npos) {
                         xdaq::ApplicationDescriptor* app = (xdaq::ApplicationDescriptor*)*j;
 
                         gem::utils::soap::GEMSOAPToolBox::sendCommand(commandOH,
@@ -1277,24 +1277,24 @@ public:
     static int initPriority(const std::string& classname)
     {
         int priority = 50; // default
+
         if (classname == "gemCrate")
-            priority = 200; // very first to check the crate connections
+            priority = 200;
         else if (classname == "tcds::lpm::LPMController")
-            priority = 102; // must be first of TCDS!
+            priority = 102;
         else if (classname == "tcds::ici::ICIController")
-            priority = 101; // must be second of TCDS!
+            priority = 101;
         else if (classname == "tcds::pi::PIController")
-            priority = 100; // must be first!?
+            priority = 100;
         else if (classname == "gem::hardware::amc13::AMC13Manager")
-            priority = 95; // after AMCManagers but not last
+            priority = 95;
         else if (classname == "gem::hardware::amc::AMCManager")
-            priority = 90; // before OH manager and before AMC13
-        else if (classname == "gem::hardware::optohybrid::OptoHybridManager")
-            priority = 55; // before AMC managers and before  AMC13
+            priority = 90;
         else if (classname == "gem::hardware::amc13::AMC13Readout")
-            priority = 30; // after AMC13Manager
+            priority = 30;
         else if (classname == "gem::hardware::gemPartitionViewer")
-            priority = 10; //
+            priority = 10;
+
         return priority;
     }
 };
@@ -1370,21 +1370,21 @@ public:
     // higher priority -- enable first
     static int enablePriority(const std::string& classname)
     {
-        int priority = 50; // default
-        if (classname == "gem::hardware::optohybrid::OptoHybridManager")
-            priority = 105; // before AMC managers
-        else if (classname == "gem::hardware::amc::AMCManager")
-            priority = 100; // after OH manager and before  AMC13
+        int priority = 50;
+
+        if (classname == "gem::hardware::amc::AMCManager")
+            priority = 100;
         else if (classname == "gem::hardware::amc13::AMC13Readout")
-            priority = 90; // before AMC13Manager
+            priority = 90;
         else if (classname == "gem::hardware::amc13::AMC13Manager")
-            priority = 35; // after AMCManagers but not last
+            priority = 35;
         else if (classname == "tcds::lpm::LPMController")
-            priority = 12; // must be first of TCDS!
+            priority = 12;
         else if (classname == "tcds::pi::PIController")
-            priority = 11; // must be before ICI!?
+            priority = 11;
         else if (classname == "tcds::ici::ICIController")
-            priority = 10; // must be last of TCDS!
+            priority = 10;
+
         return priority;
     }
 };
@@ -1444,21 +1444,21 @@ public:
     // higher priority -- disable first
     static int disablePriority(const std::string& classname)
     {
-        int priority = 50; // default
+        int priority = 50;
+
         if (classname == "tcds::lpm::LPMController")
-            priority = 102; // must be first of TCDS!
+            priority = 102;
         else if (classname == "tcds::ici::ICIController")
-            priority = 101; // must be second of TCDS!
+            priority = 101;
         else if (classname == "tcds::pi::PIController")
-            priority = 100; // must be first!?
+            priority = 100;
         else if (classname == "gem::hardware::amc13::AMC13Manager")
-            priority = 95; // after AMCManagers but not last
+            priority = 95;
         else if (classname == "gem::hardware::amc::AMCManager")
-            priority = 70; // before (or simultaneous with) OH manager and before  AMC13
-        else if (classname == "gem::hardware::optohybrid::OptoHybridManager")
-            priority = 65; // after (or simultaneous with) AMC managers and before  AMC13
+            priority = 70;
         else if (classname == "gem::hardware::amc13::AMC13Readout")
-            priority = 60; // after AMC13Manager but not last
+            priority = 60;
+
         return priority;
     }
 };
-- 
GitLab


From 315ce3b75693b056987eb6b2a3391c154862775e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Sun, 4 Oct 2020 15:33:35 +0200
Subject: [PATCH 05/19] Use the OptoHybrid mask when establishing the
 communication

---
 .../devices/interface/amc/HwGenericAMC.h      |  8 +++-
 gemhardware/devices/src/amc/HwGenericAMC.cpp  | 45 ++++++++++++++-----
 gemhardware/managers/src/AMCManager.cpp       |  2 +-
 3 files changed, 43 insertions(+), 12 deletions(-)

diff --git a/gemhardware/devices/interface/amc/HwGenericAMC.h b/gemhardware/devices/interface/amc/HwGenericAMC.h
index c5304a5b..9dabfd4f 100644
--- a/gemhardware/devices/interface/amc/HwGenericAMC.h
+++ b/gemhardware/devices/interface/amc/HwGenericAMC.h
@@ -454,15 +454,21 @@ namespace hardware {
             /// @param link is the link to perform the reset on
             virtual void linkReset(uint8_t const& link);
 
+            /// @brief Return the OptoHybrid mask for which all GBT are locked
+            uint32_t getGBTStatus();
+
             /// @brief Gets the link mask for which the communication has been established
             uint32_t connectedLinks() const;
 
             /// @brief Establishes front end communication
+            ///
             /// - performs optical links reset
             /// - configures GBTs with possibly complete configuration stored on the AMC
             /// - resets SCA module and checks SCA communication
             /// - sends an internal hard reset to trigger firmware loading to the optohybrid
-            void establishFrontEndCommunication();
+            ///
+            /// @param ohMask OptoHybrids for which to establish the communication
+            void establishFrontEndCommunication(const uint32_t optohybridMask);
 
             /// @brief Recovers the AMC
             /// - initializes Virtex7 clock
diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index 5b76454c..695f8da3 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -736,14 +736,15 @@ void gem::hardware::amc::HwGenericAMC::linkReset(uint8_t const& gtx)
     return;
 }
 
-void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication()
+uint32_t gem::hardware::amc::HwGenericAMC::getGBTStatus()
 {
     // Check status of all GBTs
     auto gbtStatus = xhal::client::call<::daqmon::getmonGBTLink>(rpc, true);
-    unsigned int optohybridMask = 0;
-    for (int i = 0; i < ::amc::OH_PER_AMC; i++) {
+
+    uint32_t optohybridMask = 0;
+    for (size_t i = 0; i < ::amc::OH_PER_AMC; i++) {
         std::vector<int> gbtReady;
-        for (int j = 0; j < ::gbt::GBTS_PER_OH; j++) {
+        for (size_t j = 0; j < ::gbt::GBTS_PER_OH; j++) {
             std::string index = "OH" + std::to_string(i) + ".GBT" + std::to_string(j) + ".READY";
             gbtReady.push_back(gbtStatus.find(index)->second);
         }
@@ -752,28 +753,52 @@ void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication()
         if (std::accumulate(gbtReady.begin(), gbtReady.end(), 1, std::multiplies<int>()) > 0)
             optohybridMask += (1 << i);
     }
-    // Call the configureGBTs rpc call for the GBT configuration, i.e. using the configuration files stored on the AMC
-    for (int i = 0; i < ::amc::OH_PER_AMC; i++) {
-        if (((optohybridMask >> i) & 0x1) == 0) // consider only the optical links with all gbts communicating
+
+    return optohybridMask;
+}
+
+void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(const uint32_t optohybridMask)
+{
+    // Check the GBT status before programming
+    uint32_t gbtStatus = getGBTStatus();
+    if ((gbtStatus & optohybridMask) != optohybridMask) {
+        std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) before programming GBT.", gbtStatus, optohybridMask);
+        CMSGEMOS_ERROR(msg);
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg);
+    }
+
+    // Call the configureGBTs RPC method for the GBT configuration, i.e. using the configuration files stored on the AMC
+    for (size_t i = 0; i < ::amc::OH_PER_AMC; i++) {
+        if (((optohybridMask >> i) & 0x1) == 0)
             continue;
+
         try {
             xhal::client::call<::gbt::configureGBTs>(rpc, i);
         }
         GEM_CATCH_RPC_ERROR("HwGenericAMC::establishFrontEndCommunication", gem::hardware::devices::exception::Exception);
     }
 
-    // reset SCA
+    // Check the GBT status after programming
+    gbtStatus = getGBTStatus();
+    if ((gbtStatus & optohybridMask) != optohybridMask) {
+        std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) after programming GBT.", gbtStatus, optohybridMask);
+        CMSGEMOS_ERROR(msg);
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg);
+    }
+
+    // Reset the SCA
     try {
         xhal::client::call<::amc::sca::scaModuleReset>(rpc, optohybridMask);
     }
     GEM_CATCH_RPC_ERROR("HwGenericAMC::establishFrontEndCommunication", gem::hardware::devices::exception::Exception);
-    // program OH FPGA
+
+    // Program the OH FPGA
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x1);
     writeReg("GEM_AMC.TTC.GENERATOR.SINGLE_HARD_RESET", 0x1);
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
     writeReg("GEM_AMC.GEM_SYSTEM.CTRL.LINK_RESET", 0x1);
 
-    // connected links are those for which the communication has been established
+    // Connected links are those for which the communication has been established
     m_links = optohybridMask;
 }
 
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index bb9c3a3d..61317809 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -114,7 +114,7 @@ void gem::hardware::AMCManager::configureAction()
 
     CMSGEMOS_INFO("AMCManager::configureAction: establish front-end communication");
     try {
-        m_amc->establishFrontEndCommunication();
+        m_amc->establishFrontEndCommunication(m_optohybridMask.value_);
     }
     GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
-- 
GitLab


From e827c9b6c8e98d98f1e01bfd8f7036b22745f1a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 19:06:19 +0200
Subject: [PATCH 06/19] Add an option to automatically disable the bad chambers

---
 doc/examples/xml/gem904daq04.xml              |  1 +
 .../devices/interface/amc/HwGenericAMC.h      | 16 +---
 gemhardware/devices/src/amc/HwGenericAMC.cpp  | 79 ++-----------------
 gemhardware/managers/interface/AMCManager.h   |  1 +
 gemhardware/managers/src/AMCManager.cpp       | 19 ++++-
 5 files changed, 27 insertions(+), 89 deletions(-)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index 48c34351..e2b49f2d 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -114,6 +114,7 @@
 
         <!-- Configuration -->
         <enableZS xsi:type="xsd:boolean">false</enableZS>
+        <autoKillOptoHybrid xsi:type="xsd:boolean">true</autoKillOptoHybrid>
       </properties>
     </xc:Application>
 
diff --git a/gemhardware/devices/interface/amc/HwGenericAMC.h b/gemhardware/devices/interface/amc/HwGenericAMC.h
index 9dabfd4f..5bcb2cae 100644
--- a/gemhardware/devices/interface/amc/HwGenericAMC.h
+++ b/gemhardware/devices/interface/amc/HwGenericAMC.h
@@ -91,12 +91,6 @@ namespace hardware {
             /// @param `reconnect` determine if the conection should be reestablished and the modules reloaded
             void connectRPC(bool reconnect = false) override;
 
-            /// Check if the gtx requested is known to be operational
-            /// @param gtx GTX to be queried
-            /// @param opMsg Operation message to append to the log message
-            /// @returns true if the GTX is in range and active, false otherwise
-            virtual bool linkCheck(uint8_t const& gtx, std::string const& opMsg);
-
         public:
             /// Set the trigger source to the front end
             /// @param uint8_t mode 0 from software, 1 from TTC decoder (AMC13), 2 from both
@@ -457,10 +451,7 @@ namespace hardware {
             /// @brief Return the OptoHybrid mask for which all GBT are locked
             uint32_t getGBTStatus();
 
-            /// @brief Gets the link mask for which the communication has been established
-            uint32_t connectedLinks() const;
-
-            /// @brief Establishes front end communication
+            /// @brief Tries to establishes the front-end communication
             ///
             /// - performs optical links reset
             /// - configures GBTs with possibly complete configuration stored on the AMC
@@ -468,7 +459,9 @@ namespace hardware {
             /// - sends an internal hard reset to trigger firmware loading to the optohybrid
             ///
             /// @param ohMask OptoHybrids for which to establish the communication
-            void establishFrontEndCommunication(const uint32_t optohybridMask);
+            ///
+            /// @return OptoHybrids for which all GBT links were valid at the start of the procedure
+            uint32_t establishFrontEndCommunication(uint32_t optohybridMask);
 
             /// @brief Recovers the AMC
             /// - initializes Virtex7 clock
@@ -482,7 +475,6 @@ namespace hardware {
             void recoverAMC();
 
         protected:
-            uint32_t m_links; ///< Connected links mask
             uint32_t m_maxLinks; ///< Maximum supported OptoHybrids as reported by the firmware
 
             /// @brief sets the expected board ID string to be matched when reading from the firmware
diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index 695f8da3..11b750fa 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -14,7 +14,6 @@
 
 gem::hardware::amc::HwGenericAMC::HwGenericAMC(std::string const& amcDevice)
     : gem::hardware::GEMHwDevice::GEMHwDevice(amcDevice)
-    , m_links(0)
     , m_maxLinks(gem::hardware::utils::N_GTX)
 {
     CMSGEMOS_INFO("HwGenericAMC ctor");
@@ -189,63 +188,6 @@ std::string gem::hardware::amc::HwGenericAMC::getUserFirmwareDate()
     return res.str();
 }
 
-bool gem::hardware::amc::HwGenericAMC::linkCheck(uint8_t const& gtx, std::string const& opMsg)
-{
-    CMSGEMOS_INFO("linkCheck:: m_links 0x" << std::hex << std::setw(8) << std::setfill('0')
-                                           << m_links << std::dec);
-    if (gtx > m_maxLinks) {
-        std::string msg = toolbox::toString("%s requested for gtx (%d): outside expectation (0-%d)",
-            opMsg.c_str(), gtx, m_maxLinks);
-        CMSGEMOS_ERROR(msg);
-        // XCEPT_RAISE(gem::hardware::devices::exception::InvalidLink,msg);
-        return false;
-    } else if (!((m_links >> gtx) & 0x1)) {
-        CMSGEMOS_INFO("linkCheck:: m_links 0x" << std::hex << std::setw(8) << std::setfill('0')
-                                               << m_links << std::dec);
-        std::string msg = toolbox::toString("%s requested inactive gtx (%d, 0x%08x, 0x%08x)",
-            opMsg.c_str(), gtx, m_links, m_links >> gtx);
-        CMSGEMOS_ERROR(msg);
-        // XCEPT_RAISE(gem::hardware::devices::exception::InvalidLink,msg);
-        return false;
-    }
-    CMSGEMOS_INFO("linkCheck:: m_links 0x" << std::hex << std::setw(8) << std::setfill('0')
-                                           << m_links << std::dec);
-    return true;
-}
-
-// FIXME UPDATE //
-// gem::hardware::GEMHwDevice::OpticalLinkStatus gem::hardware::amc::HwGenericAMC::LinkStatus(uint8_t const& gtx)
-// {
-//   gem::hardware::GEMHwDevice::OpticalLinkStatus linkStatus;
-//   // FIXME moved to OH GEM_AMC.OH.OH0.FPGA.GBT.RX.CNT_LINK_ERR
-//   CMSGEMOS_INFO("LinkStatus:: m_links 0x" << std::hex <<std::setw(8) << std::setfill('0')
-//                 << m_links << std::dec);
-//   if (linkCheck(gtx, "Link status")) {
-//     linkStatus.GTX_TRK_Errors   = readReg("GEM_AMC."+toolbox::toString("OH_LINKS.OH%d.TRACK_LINK_ERROR_CNT", gtx));
-//     linkStatus.GTX_TRG_Errors   = readReg("GEM_AMC."+toolbox::toString("TRIGGER.OH%d.LINK0_MISSED_COMMA_CNT",gtx));
-//     linkStatus.GTX_Data_Packets = readReg("GEM_AMC."+toolbox::toString("OH_LINKS.OH%d.VFAT_BLOCK_CNT",       gtx));
-//     linkStatus.GBT_TRK_Errors   = readReg("GEM_AMC."+toolbox::toString("OH_LINKS.OH%d.TRACK_LINK_ERROR_CNT", gtx));
-//     linkStatus.GBT_Data_Packets = readReg("GEM_AMC."+toolbox::toString("OH_LINKS.OH%d.VFAT_BLOCK_CNT",       gtx));
-//   }
-//   CMSGEMOS_INFO("LinkStatus:: m_links 0x" << std::hex <<std::setw(8) << std::setfill('0')
-//                 << m_links << std::dec);
-//   return linkStatus;
-// }
-
-// FIXME UPDATE //
-// void gem::hardware::amc::HwGenericAMC::LinkReset(uint8_t const& gtx, uint8_t const& resets)
-// {
-//   // FIXME right now this just resets the counters, but we need to be able to "reset" the link too
-//   if (linkCheck(gtx, "Link reset")) {
-//     if (resets&0x1)
-//       writeReg("GEM_AMC."+toolbox::toString("OH_LINKS.CTRL.CNT_RESET"), gtx);
-//     if (resets&0x2)
-//       writeReg("GEM_AMC."+toolbox::toString("TRIGGER.CTRL.CNT_RESET"),  gtx);
-//     if (resets&0x4)
-//       writeReg("GEM_AMC."+toolbox::toString("OH_LINKS.CTRL.CNT_RESET"), gtx);
-//   }
-// }
-
 uint32_t gem::hardware::amc::HwGenericAMC::readTriggerFIFO(uint8_t const& gtx)
 {
     // V2 firmware hasn't got trigger fifo yet
@@ -757,15 +699,10 @@ uint32_t gem::hardware::amc::HwGenericAMC::getGBTStatus()
     return optohybridMask;
 }
 
-void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(const uint32_t optohybridMask)
+uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32_t optohybridMask)
 {
-    // Check the GBT status before programming
-    uint32_t gbtStatus = getGBTStatus();
-    if ((gbtStatus & optohybridMask) != optohybridMask) {
-        std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) before programming GBT.", gbtStatus, optohybridMask);
-        CMSGEMOS_ERROR(msg);
-        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg);
-    }
+    // Use only the working OptoHybrids
+    optohybridMask = getGBTStatus() & optohybridMask;
 
     // Call the configureGBTs RPC method for the GBT configuration, i.e. using the configuration files stored on the AMC
     for (size_t i = 0; i < ::amc::OH_PER_AMC; i++) {
@@ -779,7 +716,7 @@ void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(const uint
     }
 
     // Check the GBT status after programming
-    gbtStatus = getGBTStatus();
+    const uint32_t gbtStatus = getGBTStatus();
     if ((gbtStatus & optohybridMask) != optohybridMask) {
         std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) after programming GBT.", gbtStatus, optohybridMask);
         CMSGEMOS_ERROR(msg);
@@ -798,13 +735,7 @@ void gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(const uint
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
     writeReg("GEM_AMC.GEM_SYSTEM.CTRL.LINK_RESET", 0x1);
 
-    // Connected links are those for which the communication has been established
-    m_links = optohybridMask;
-}
-
-uint32_t gem::hardware::amc::HwGenericAMC::connectedLinks() const
-{
-    return m_links;
+    return optohybridMask;
 }
 
 void gem::hardware::amc::HwGenericAMC::configureAMCCalDataFormat(bool en)
diff --git a/gemhardware/managers/interface/AMCManager.h b/gemhardware/managers/interface/AMCManager.h
index ea2e4ffd..502fca18 100644
--- a/gemhardware/managers/interface/AMCManager.h
+++ b/gemhardware/managers/interface/AMCManager.h
@@ -57,6 +57,7 @@ namespace hardware {
 
         // Configuration
         xdata::Boolean m_enableZS = false; ///< Enable the zero-suppression
+        xdata::Boolean m_autoKillOptoHybrid = false; ///< Automatically disable non-communicating OptoHybrids during the configuration step
 
         amc_shared_ptr m_amc; ///< AMC hardware object
         std::array<optohybrid_shared_ptr, MAX_OPTOHYBRIDS_PER_AMC> m_optohybrids; ///< OptoHybrid hardware objects
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index 61317809..87526f5c 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -31,16 +31,19 @@ gem::hardware::AMCManager::AMCManager(xdaq::ApplicationStub* stub)
     p_appInfoSpace->fireItemAvailable("slot", &m_slot);
     p_appInfoSpace->fireItemAvailable("optohybridMask", &m_optohybridMask);
     p_appInfoSpace->fireItemAvailable("enableZS", &m_enableZS);
+    p_appInfoSpace->fireItemAvailable("autoKillOptoHybrid", &m_autoKillOptoHybrid);
 
     p_appInfoSpace->addItemRetrieveListener("crate", this);
     p_appInfoSpace->addItemRetrieveListener("slot", this);
     p_appInfoSpace->addItemRetrieveListener("optohybridMask", this);
     p_appInfoSpace->addItemRetrieveListener("enableZS", this);
+    p_appInfoSpace->addItemRetrieveListener("autoKillOptoHybrid", this);
 
     p_appInfoSpace->addItemChangedListener("crate", this);
     p_appInfoSpace->addItemChangedListener("slot", this);
     p_appInfoSpace->addItemChangedListener("optohybridMask", this);
     p_appInfoSpace->addItemChangedListener("enableZS", this);
+    p_appInfoSpace->addItemChangedListener("autoKillOptoHybrid", this);
 
     xoap::bind<gem::base::GEMApplication>(this, &gem::base::GEMApplication::calibParamRetrieve, "calibParamRetrieve", XDAQ_NS_URI);
     xoap::bind(this, &gem::hardware::AMCManager::setRunTypeInterCalib, "setRunTypeInterCalib", XDAQ_NS_URI);
@@ -114,14 +117,24 @@ void gem::hardware::AMCManager::configureAction()
 
     CMSGEMOS_INFO("AMCManager::configureAction: establish front-end communication");
     try {
-        m_amc->establishFrontEndCommunication(m_optohybridMask.value_);
+        const uint32_t workingOptoHybridMask = m_amc->establishFrontEndCommunication(m_optohybridMask.value_);
+
+        if (m_autoKillOptoHybrid.value_) {
+            m_optohybridMask.value_ = workingOptoHybridMask;
+        } else if (m_optohybridMask != workingOptoHybridMask) {
+            std::stringstream errmsg;
+            errmsg << "AMCManager::configureAction: impossible to establish communication with all OptoHybrids";
+            CMSGEMOS_ERROR(errmsg.str());
+            XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
+        }
+
+        CMSGEMOS_INFO("AMCManager::configureAction: using optohybridMask: 0x" << std::hex << m_optohybridMask);
     }
     GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
     CMSGEMOS_INFO("AMCManager::configureAction: configure DAQ module");
-    const bool inputEnableMask = m_amc->connectedLinks();
     try {
-        m_amc->configureDAQModule(inputEnableMask, m_enableZS.value_);
+        m_amc->configureDAQModule(m_optohybridMask.value_, m_enableZS.value_);
     }
     GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
 
-- 
GitLab


From 0cbc9791bda6211bff7c208675da9bde598f48d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 16:39:18 +0200
Subject: [PATCH 07/19] Add layer 2 in the gem904daq04 xDAQ configuration

---
 doc/examples/xml/gem904daq04.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index e2b49f2d..c48ecc52 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -110,7 +110,7 @@
         <!-- Hardware description -->
         <crate xsi:type="xsd:unsignedInt">1</crate>
         <slot xsi:type="xsd:unsignedInt">2</slot>
-        <optohybridMask xsi:type="xsd:unsignedInt">0x1</optohybridMask>
+        <optohybridMask xsi:type="xsd:unsignedInt">0x3</optohybridMask>
 
         <!-- Configuration -->
         <enableZS xsi:type="xsd:boolean">false</enableZS>
-- 
GitLab


From f7ecfa8ca6814499e6ca57b98483b2b5cfebfb1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Thu, 8 Oct 2020 17:23:51 +0200
Subject: [PATCH 08/19] Define better the xDAQ application numbers and port

---
 doc/examples/README.md           |  2 +-
 doc/examples/scripts/run_xdaq.sh |  2 +-
 doc/examples/xml/gem904daq04.xml | 78 +++++++++++++++++---------------
 3 files changed, 44 insertions(+), 38 deletions(-)

diff --git a/doc/examples/README.md b/doc/examples/README.md
index ac33227c..1234df99 100644
--- a/doc/examples/README.md
+++ b/doc/examples/README.md
@@ -20,7 +20,7 @@ sh doc/examples/scripts/run_xdaq.sh
 ```
 
 This will launch the xdaq process with the default XML [configuration](xml/gemsupervisor.xml),
-written for GEM 904 integration setup and using port 20502. 
+written for GEM 904 integration setup and using port 20100.
 
 The GBT configurations examples can be found under `gemrpc/doc/gbt/<gem type>/`, but the files used for the configuration of the chamber are stored on the AMC folder `/mnt/persistent/gempro/etc/gem/gbt`.
 The example files contain the phases derived as discussed in issue [#35](https://gitlab.cern.ch/cmsgemonline/cmsgemos/issues/35).
diff --git a/doc/examples/scripts/run_xdaq.sh b/doc/examples/scripts/run_xdaq.sh
index 2ae8f5ec..479a3e5e 100644
--- a/doc/examples/scripts/run_xdaq.sh
+++ b/doc/examples/scripts/run_xdaq.sh
@@ -18,4 +18,4 @@ export AMC13_ADDRESS_TABLE_PATH=/opt/cactus/etc/amc13
 (GLOBIGNORE=gemdaq; ln -snf /opt/xdaq/htdocs/* ${CMSGEMOS_DATADIR}/htdocs/)
 
 # Start xDAQ
-/opt/xdaq/bin/xdaq.exe -c ${SCRIPT_DIR}/../xml/gem904daq04.xml -p 20502 $@
+/opt/xdaq/bin/xdaq.exe -c ${SCRIPT_DIR}/../xml/gem904daq04.xml -p 20100 $@
diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index c48ecc52..a59a1e7d 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -2,11 +2,12 @@
 <xc:Partition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
               xmlns:xc="http://xdaq.web.cern.ch/xdaq/xsd/2004/XMLConfiguration-30">
-  <xc:Context url="http://gem904daq04:20502">
+  <xc:Context url="http://gem904daq04:20100">
 
     <xc:Module>${CMSGEMOS_LIBDIR}/libgemsupervisor.so</xc:Module>
 
-    <xc:Application class="gem::supervisor::GEMSupervisor" id="16" instance="0" network="local">
+    <!-- ID: 10; instance: 0 -->
+    <xc:Application class="gem::supervisor::GEMSupervisor" id="10" instance="0" network="local">
       <properties xmlns="urn:xdaq-application:GEMSupervisor" xsi:type="soapenc:Struct">
         <UseLocalReadout xsi:type="xsd:boolean">true</UseLocalReadout>
         <UseFedKitReadout xsi:type="xsd:boolean">false</UseFedKitReadout>
@@ -23,26 +24,33 @@
       </properties>
     </xc:Application>
 
+    <xc:Module>${CMSGEMOS_LIBDIR}/libgemcalibration.so</xc:Module>
+
+    <!-- ID: 20; instance: 0 -->
+    <xc:Application class="gem::calibration::Calibration" id="20" instance="0" network="local">
+        <properties xmlns="urn:xdaq-application:gem::calibration::Calibration" xsi:type="soapenc:Struct">
+            <nShelves xsi:type="xsd:integer">1</nShelves>
+        </properties>
+    </xc:Application>
+
     <xc:Module>${CMSGEMOS_LIBDIR}/libgemhardware_managers.so</xc:Module>
 
-    <xc:Application class="gem::hardware::amc13::AMC13Readout" id="260" instance="0" network="local">
-      <properties xmlns="urn:xdaq-application:gem::hardware::amc13::AMC13Readout" xsi:type="soapenc:Struct">
-        <ConnectionFile xsi:type="xsd:string">connections.xml</ConnectionFile>
-        <CardName xsi:type="xsd:string">gem.shelf01.amc13</CardName>
-        <DeviceName xsi:type="xsd:string">AMC13</DeviceName>
-        <crateID xsi:type="xsd:integer">1</crateID>
-        <slot xsi:type="xsd:integer">13</slot>
-        <ReadoutSettings xsi:type="soapenc:Struct">
-          <runType xsi:type="xsd:string">Testing</runType>
-          <fileName xsi:type="xsd:string">test</fileName>
-          <outputType xsi:type="xsd:string">BIN</outputType>
-          <outputLocation xsi:type="xsd:string">/tmp/</outputLocation>
-          <setupLocation xsi:type="xsd:string">CERN904</setupLocation>
-        </ReadoutSettings>
+    <!-- ID: xyy, x = shelf, yy = slot; instance: 12*shelf+slot -->
+    <xc:Application class="gem::hardware::AMCManager" id="102" instance="14" network="local">
+      <properties xmlns="urn:xdaq-application:gem::hardware::AMCManager" xsi:type="soapenc:Struct">
+        <!-- Hardware description -->
+        <crate xsi:type="xsd:unsignedInt">1</crate>
+        <slot xsi:type="xsd:unsignedInt">2</slot>
+        <optohybridMask xsi:type="xsd:unsignedInt">0x3</optohybridMask>
+
+        <!-- Configuration -->
+        <enableZS xsi:type="xsd:boolean">false</enableZS>
+        <autoKillOptoHybrid xsi:type="xsd:boolean">true</autoKillOptoHybrid>
       </properties>
     </xc:Application>
 
-    <xc:Application class="gem::hardware::amc13::AMC13Manager" id="255" instance="3" network="local">
+    <!-- ID: x13, x = shelf; instance: shelf -->
+    <xc:Application class="gem::hardware::amc13::AMC13Manager" id="113" instance="1" network="local">
       <properties xmlns="urn:xdaq-application:gem::hardware::amc13::AMC13Manager" xsi:type="soapenc:Struct">
         <amc13ConfigParams xsi:type="soapenc:Struct">
           <ConnectionFile xsi:type="xsd:string">connections.xml</ConnectionFile>
@@ -105,30 +113,28 @@
       </properties>
     </xc:Application>
 
-    <xc:Application class="gem::hardware::AMCManager" id="30" instance="0" network="local">
-      <properties xmlns="urn:xdaq-application:gem::hardware::AMCManager" xsi:type="soapenc:Struct">
-        <!-- Hardware description -->
-        <crate xsi:type="xsd:unsignedInt">1</crate>
-        <slot xsi:type="xsd:unsignedInt">2</slot>
-        <optohybridMask xsi:type="xsd:unsignedInt">0x3</optohybridMask>
-
-        <!-- Configuration -->
-        <enableZS xsi:type="xsd:boolean">false</enableZS>
-        <autoKillOptoHybrid xsi:type="xsd:boolean">true</autoKillOptoHybrid>
+    <!-- ID: x14, x = shelf; instance: shelf -->
+    <xc:Application class="gem::hardware::amc13::AMC13Readout" id="114" instance="1" network="local">
+      <properties xmlns="urn:xdaq-application:gem::hardware::amc13::AMC13Readout" xsi:type="soapenc:Struct">
+        <ConnectionFile xsi:type="xsd:string">connections.xml</ConnectionFile>
+        <CardName xsi:type="xsd:string">gem.shelf01.amc13</CardName>
+        <DeviceName xsi:type="xsd:string">AMC13</DeviceName>
+        <crateID xsi:type="xsd:integer">1</crateID>
+        <slot xsi:type="xsd:integer">13</slot>
+        <ReadoutSettings xsi:type="soapenc:Struct">
+          <runType xsi:type="xsd:string">Testing</runType>
+          <fileName xsi:type="xsd:string">test</fileName>
+          <outputType xsi:type="xsd:string">BIN</outputType>
+          <outputLocation xsi:type="xsd:string">/tmp/</outputLocation>
+          <setupLocation xsi:type="xsd:string">CERN904</setupLocation>
+        </ReadoutSettings>
       </properties>
     </xc:Application>
 
-    <xc:Module>${CMSGEMOS_LIBDIR}/libgemcalibration.so</xc:Module>
-
-    <xc:Application class="gem::calibration::Calibration" id="17" instance="0" network="local">
-        <properties xmlns="urn:xdaq-application:gem::calibration::Calibration" xsi:type="soapenc:Struct">
-            <nShelves xsi:type="xsd:integer">2</nShelves>
-        </properties>
-    </xc:Application>
-
     <xc:Module>${CMSGEMOS_LIBDIR}/libgemmonitor.so</xc:Module>
 
-    <xc:Application class="gem::monitor::ShelfMonitor" id="18" instance="0" network="local">
+    <!-- ID: x00, x = shelf; instance: shelf -->
+    <xc:Application class="gem::monitor::ShelfMonitor" id="100" instance="1" network="local">
       <properties xmlns="urn:xdaq-application:ShelfMonitor" xsi:type="soapenc:Struct">
         <shelfID  xsi:type="xsd:integer">1</shelfID>
         <doWriteLog  xsi:type="xsd:boolean">false</doWriteLog>
-- 
GitLab


From 8197156a2ee1b747462fef4a734dec2b931e5dbc Mon Sep 17 00:00:00 2001
From: Camilla Galloni <camilla.galloni@cern.ch>
Date: Thu, 8 Oct 2020 21:30:51 +0200
Subject: [PATCH 09/19] Update latency value only once

---
 gemhardware/managers/src/AMCManager.cpp | 10 ----------
 1 file changed, 10 deletions(-)

diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index 87526f5c..a4c3052b 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -596,16 +596,6 @@ xoap::MessageReference gem::hardware::AMCManager::updateScanValueCalib(xoap::Mes
             }
         }
 
-        // Update the scan parameters
-        if (m_scanInfo.bag.scanType.value_ == 2) {
-            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan old Latency " << static_cast<uint32_t>(m_lastLatency));
-            m_lastLatency += m_scanInfo.bag.stepSize.value_;
-            CMSGEMOS_INFO("AMCManager::pauseAction LatencyScan new Latency " << static_cast<uint32_t>(m_lastLatency));
-        } else if (m_scanInfo.bag.scanType.value_ == 3) {
-            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan old VT1 " << static_cast<uint32_t>(m_lastVT1));
-            m_lastVT1 += m_scanInfo.bag.stepSize.value_;
-            CMSGEMOS_INFO("AMCManager::pauseAction ThresholdScan new VT1 " << static_cast<uint32_t>(m_lastVT1));
-        }
         CMSGEMOS_INFO("AMCManager::updateScanValueCalib end");
 
         return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "Done");
-- 
GitLab


From 89528564e1248feacb706cd18848aa56e3d8cf50 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Tue, 6 Oct 2020 23:19:24 +0200
Subject: [PATCH 10/19] Allow to transition from one state to itself

While triggering a state transition from a stable state to itself, it is
important to update the managed applications first in order to retrieve
the correct transitional state. If not done, the transition is seen as
instantaneous by the supervisor which moves to the new set of
applications.

The fix may still be subject to race conditions, but worked very until
now. A better solution will be implemented later together with the FSM
refactoring.
---
 gemsupervisor/src/GEMSupervisor.cpp | 56 ++++++++++++++---------------
 1 file changed, 28 insertions(+), 28 deletions(-)

diff --git a/gemsupervisor/src/GEMSupervisor.cpp b/gemsupervisor/src/GEMSupervisor.cpp
index 0aad4714..effc6f41 100644
--- a/gemsupervisor/src/GEMSupervisor.cpp
+++ b/gemsupervisor/src/GEMSupervisor.cpp
@@ -286,12 +286,12 @@ void gem::supervisor::GEMSupervisor::initializeAction()
                 }
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_HALTED) {
-                CMSGEMOS_DEBUG("GEMSupervisor::initializeAction waiting for group to reach Halted: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::initializeAction waiting for group to reach Halted: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_HALTED);
         }
         // why is initializeAction treated differently than the other state transitions?
         // should make this uniform, or was it due to wanting to fail on DB errors?
@@ -434,12 +434,12 @@ void gem::supervisor::GEMSupervisor::configureAction()
                 }
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_CONFIGURED) {
-                CMSGEMOS_DEBUG("GEMSupervisor::configureAction waiting for group to reach Configured: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::configureAction waiting for group to reach Configured: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_CONFIGURED);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
@@ -528,12 +528,12 @@ void gem::supervisor::GEMSupervisor::startAction()
                 }
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_RUNNING) {
-                CMSGEMOS_DEBUG("GEMSupervisor::startAction waiting for group to reach Running: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::startAction waiting for group to reach Running: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_RUNNING);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
@@ -599,12 +599,12 @@ void gem::supervisor::GEMSupervisor::pauseAction()
                 gem::utils::soap::GEMSOAPToolBox::sendCommand("Pause", p_appContext, p_appDescriptor, *j);
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_PAUSED) {
-                CMSGEMOS_DEBUG("GEMSupervisor::pauseAction waiting for group to reach Paused: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::pauseAction waiting for group to reach Paused: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_PAUSED);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
@@ -670,12 +670,12 @@ void gem::supervisor::GEMSupervisor::resumeAction()
                 gem::utils::soap::GEMSOAPToolBox::sendCommand("Resume", p_appContext, p_appDescriptor, *j);
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_RUNNING) {
-                CMSGEMOS_DEBUG("GEMSupervisor::resumeAction waiting for group to reach Running: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::resumeAction waiting for group to reach Running: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_RUNNING);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
@@ -742,12 +742,12 @@ void gem::supervisor::GEMSupervisor::stopAction()
                 gem::utils::soap::GEMSOAPToolBox::sendCommand("Stop", p_appContext, p_appDescriptor, *j);
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_CONFIGURED) {
-                CMSGEMOS_DEBUG("GEMSupervisor::stopAction waiting for group to reach Configured: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::stopAction waiting for group to reach Configured: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_CONFIGURED);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
@@ -805,12 +805,12 @@ void gem::supervisor::GEMSupervisor::haltAction()
                 gem::utils::soap::GEMSOAPToolBox::sendCommand("Halt", p_appContext, p_appDescriptor, *j);
             }
             // check that group state of *i has moved to desired state before continuing
-            while (m_globalState.compositeState(*i) != gem::base::STATE_HALTED) {
-                CMSGEMOS_DEBUG("GEMSupervisor::haltAction waiting for group to reach Halted: "
-                    << m_globalState.compositeState(*i));
+            do {
                 usleep(10);
                 m_globalState.update();
-            }
+                CMSGEMOS_DEBUG("GEMSupervisor::haltAction waiting for group to reach Halted: "
+                    << m_globalState.compositeState(*i));
+            } while (m_globalState.compositeState(*i) != gem::base::STATE_HALTED);
         }
     } catch (gem::supervisor::exception::Exception const& e) {
         std::stringstream msg;
-- 
GitLab


From b18ada8757eabb5df13a94b2142677a9f9a46463 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Sun, 4 Oct 2020 12:43:43 +0200
Subject: [PATCH 11/19] Set the BX offset between the AMC13 and AMC

---
 gemhardware/managers/src/amc13/AMC13Manager.cpp | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/gemhardware/managers/src/amc13/AMC13Manager.cpp b/gemhardware/managers/src/amc13/AMC13Manager.cpp
index 1534fef6..39d6c77d 100644
--- a/gemhardware/managers/src/amc13/AMC13Manager.cpp
+++ b/gemhardware/managers/src/amc13/AMC13Manager.cpp
@@ -392,6 +392,10 @@ void gem::hardware::amc13::AMC13Manager::initializeAction()
 
 void gem::hardware::amc13::AMC13Manager::configureAction()
 {
+    // Set the offset between the AMC13 BX counter and AMC BX counter
+    // Starts at 0 on the AMC13, and at 1 on the AMC
+    p_amc13->write(::amc13::AMC13::T1, "CONF.BCN_OFFSET", 1);
+
     /* REDUNDANT?
   if (m_enableLocalL1A) {
     m_L1Aburst = m_localTriggerConfig.bag.l1Aburst.value_;
-- 
GitLab


From 2c4c9c1ce9b2d59c3f33111682eed7d5b14dae6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Wed, 18 Nov 2020 16:04:37 +0100
Subject: [PATCH 12/19] Separate AMC recovery and clocks reset

---
 .../devices/interface/amc/HwGenericAMC.h      |  13 +--
 gemhardware/devices/src/amc/HwGenericAMC.cpp  |  13 ++-
 gemhardware/managers/src/AMCManager.cpp       |  17 ++-
 gemrpc/interface/amc.h                        |  28 ++++-
 gemrpc/src/amc.cpp                            | 103 +++++++++++-------
 5 files changed, 113 insertions(+), 61 deletions(-)

diff --git a/gemhardware/devices/interface/amc/HwGenericAMC.h b/gemhardware/devices/interface/amc/HwGenericAMC.h
index 5bcb2cae..d652a85c 100644
--- a/gemhardware/devices/interface/amc/HwGenericAMC.h
+++ b/gemhardware/devices/interface/amc/HwGenericAMC.h
@@ -463,17 +463,12 @@ namespace hardware {
             /// @return OptoHybrids for which all GBT links were valid at the start of the procedure
             uint32_t establishFrontEndCommunication(uint32_t optohybridMask);
 
-            /// @brief Recovers the AMC
-            /// - initializes Virtex7 clock
-            /// - loads the firmware for the AMC
-            /// - enables Opto TX lasers
-            /// - configures the GTH with proper polarity
-            /// - writes the TTC alignment phases
-            /// - resets the sync counters and the GTH alignement
-            /// - checks the GTH channels status
-            /// - loads the OH firmware in the RAM from promless programming
+            /// @brief Recovers the AMC (see RPC method documentation)
             void recoverAMC();
 
+            /// @brief Resets all the AMC clocks (see RPC method documentation)
+            void resetClocks();
+
         protected:
             uint32_t m_maxLinks; ///< Maximum supported OptoHybrids as reported by the firmware
 
diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index 11b750fa..a1737a27 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -718,7 +718,7 @@ uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32
     // Check the GBT status after programming
     const uint32_t gbtStatus = getGBTStatus();
     if ((gbtStatus & optohybridMask) != optohybridMask) {
-        std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) after programming GBT.", gbtStatus, optohybridMask);
+        const std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) after programming GBT.", gbtStatus, optohybridMask);
         CMSGEMOS_ERROR(msg);
         XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg);
     }
@@ -744,6 +744,7 @@ void gem::hardware::amc::HwGenericAMC::configureAMCCalDataFormat(bool en)
 
     return;
 }
+
 void gem::hardware::amc::HwGenericAMC::recoverAMC()
 {
     try {
@@ -753,3 +754,13 @@ void gem::hardware::amc::HwGenericAMC::recoverAMC()
 
     return;
 }
+
+void gem::hardware::amc::HwGenericAMC::resetClocks()
+{
+    try {
+        xhal::client::call<::amc::resetClocks>(rpc);
+    }
+    GEM_CATCH_RPC_ERROR("HwGenericAMC::resetClocks", gem::hardware::devices::exception::Exception);
+
+    return;
+}
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index a4c3052b..b0f9eec0 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -83,6 +83,12 @@ void gem::hardware::AMCManager::initializeAction()
     }
     GEM_HARDWARE_TRANSITION_CATCH("AMCManager::initializeAction", gem::hardware::devices::exception::Exception);
 
+    CMSGEMOS_INFO("AMCManager::initializeAction: recover AMC");
+    try {
+        m_amc->recoverAMC();
+    }
+    GEM_CATCH_RPC_ERROR("AMCManager::initializeAction", gem::hardware::devices::exception::ConfigurationProblem);
+
     // == OptoHybrids ==
     for (size_t link = 0; link < MAX_OPTOHYBRIDS_PER_AMC; ++link) {
         if (!((m_optohybridMask.value_ >> link) & 0x1))
@@ -103,11 +109,6 @@ void gem::hardware::AMCManager::configureAction()
     CMSGEMOS_INFO("AMCManager::configureAction begin");
 
     // == AMC ==
-
-    // Recover AMC: check clocks, reload AMC FW, restart RPC sevice
-    CMSGEMOS_INFO("AMCManager::configureAction: recover AMC");
-    m_amc->recoverAMC();
-
     if (!m_amc->isHwConnected()) {
         std::stringstream errmsg;
         errmsg << "AMCManager::configureAction AMC in slot " << m_slot.value_ << " is not connected";
@@ -115,6 +116,12 @@ void gem::hardware::AMCManager::configureAction()
         XCEPT_RAISE(gem::hardware::devices::exception::Exception, errmsg.str());
     }
 
+    CMSGEMOS_INFO("AMCManager::configureAction: reset clocks");
+    try {
+        m_amc->resetClocks();
+    }
+    GEM_CATCH_RPC_ERROR("AMCManager::configureAction", gem::hardware::devices::exception::ConfigurationProblem);
+
     CMSGEMOS_INFO("AMCManager::configureAction: establish front-end communication");
     try {
         const uint32_t workingOptoHybridMask = m_amc->establishFrontEndCommunication(m_optohybridMask.value_);
diff --git a/gemrpc/interface/amc.h b/gemrpc/interface/amc.h
index 365edbdb..9b4e320c 100644
--- a/gemrpc/interface/amc.h
+++ b/gemrpc/interface/amc.h
@@ -89,15 +89,33 @@ struct sbitReadOut : public xhal::common::Method {
 struct repeatedRegRead : public xhal::common::Method {
     std::map<std::string, uint32_t> operator()(const std::vector<std::string>& regList, const bool& breakOnFailure = false, const uint32_t& nReads = 100) const;
 };
-/// @brief Recovers the AMC by reconfiguring the V7 clock, loading the firmware for the AMC, enabling the Opto TX lasers, configuring the GTH with proper polarity, i.e. regular and inverted for channel 11, 36, and 37, writing the TTC alignment phases and resetting the sync counters, resetting the GTH channels and checking their status, loads the OH firmware to the RAM for promless programming
+
+/// @brief Recovers the AMC
+///
+/// * Enable the optical TX lasers
+/// * Reset the FPGA registers
+/// * Configure the GTH transceivers
+///
 /// @throws @c std::runtime::error if
-///         * failes to initialize the clock
-///         * failes to load AMC firmware;
-///         * failes to enaable Opto TX Laser;
-///         * failes to load OH FW to the RAM;
+///         * fails to enable the optical TX lasers.
 struct recoverAMC : public xhal::common::Method {
     void operator()() const;
 };
+
+/// @brief Resets all the AMC clocks
+///
+/// * Reset the external PLL (Si5324)
+/// * Reset the internal PLL
+/// * Reset the FPGA logic after clock changes
+/// * Align the clock phase to the TTC backplane clock
+/// * Reset the GTH transceivers
+///
+/// @throws @c std::runtime::error if
+///         * fails to reset the external PLL;
+///         * fails to reset the internal PLL.
+struct resetClocks : public xhal::common::Method {
+    void operator()() const;
+};
 }
 
 #endif
diff --git a/gemrpc/src/amc.cpp b/gemrpc/src/amc.cpp
index 87661fc8..eeb12409 100644
--- a/gemrpc/src/amc.cpp
+++ b/gemrpc/src/amc.cpp
@@ -157,49 +157,71 @@ std::vector<uint32_t> amc::sbitReadOut::operator()(const uint32_t& ohN, const ui
 
 void amc::recoverAMC::operator()() const
 {
-    LOG4CPLUS_INFO(logger, "Reconfiguring Virtex7");
-
-    // Try to ensure there is no AXI bus transaction in flight
-    std::this_thread::sleep_for(std::chrono::milliseconds(50));
-
-    // First initialize ref clocks before loading the V7 firmware (160 MHz refclk)
-    if (system("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A0 A0 A0"))
-        throw std::runtime_error("Failed to initialize clock");
-    // Wait for the PLL to lock
-    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
-
-    LOG4CPLUS_INFO(logger, "clock initialized");
-    if (system("/bin/v7load /mnt/persistent/gemdaq/fw/gem_ctp7.bit"))
-        throw std::runtime_error("Failed to load AMC firmware");
-
-    // There is 1 second of delay when the AMC firmware is loaded in which accessing the addresses is impossible
-    std::this_thread::sleep_for(std::chrono::milliseconds(1200));
-
-    // Enable Opto TX Lasers
+    // Step 1: Enable the optical TX lasers
+    LOG4CPLUS_INFO(logger, "Enable the optical TX lasers");
     if (system("/bin/txpower enable")) {
-        //FIXME::do not throw exception because it will fail on the coffin setup where there is a faulty TX Laser
-        //throw std::runtime_error("Failed to disable Opto TX Laser");
+        throw std::runtime_error("Failed to enable the optical TX lasers");
     }
-    //Configure GTHs in optical mode with tx polarity inverted
-    // Regular GTH config/ctrl value:
-    // Bit 0: = 0, TX_POWERDOWN: Transmitter powered down
-    // Bit 1: = 0, RX_POWERDOWN: Receiver active
-    // Bit 2: = 1, TX_POLARITY: not inverted
-    // Bit 3: = 0, RX_POLARITY: not inverted
-    // Bit 4: = 0, LOOPBACK: not active
-    // Bit 5: = 0, TX_INHIBIT: TX laser deactived
-    // Bit 6: = 1, RX_LOW_POWER_MODE: RX equalizer low power mode enabled!!
 
+    // Step 2: Reset the FPGA registers
+    utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.IPBUS_RESET", 1);
+
+    // Step 3: Configure the GTH transceivers
+    //
+    // Regular GTH config/control value:
+    // Bit 0: TX_POWERDOWN: Transmitter powered down
+    // Bit 1: RX_POWERDOWN: Receiver active
+    // Bit 2: TX_POLARITY: not inverted
+    // Bit 3: RX_POLARITY: not inverted
+    // Bit 4: LOOPBACK: not active
+    // Bit 5: TX_INHIBIT: TX laser deactived
+    // Bit 6: RX_LOW_POWER_MODE: RX equalizer low power mode enabled
+    LOG4CPLUS_INFO(logger, "Configure the GTH transceivers");
     for (uint32_t i = 0; i < 64; i++) {
         const auto tmp = std::string { "GEM_AMC.OPTICAL_LINKS.MGT_CHANNEL_" } + std::to_string(i) + ".CTRL";
-        if (i == 11 || i == 36 || i == 37) {
+        if (i == 11) {
             utils::writeReg(tmp, 0x4c);
+        } else if (i == 36 || i == 37) {
+            utils::writeReg(tmp, 0x48);
+        } else if (i > 35) {
+            utils::writeReg(tmp, 0x40);
         } else {
             utils::writeReg(tmp, 0x44);
         }
     }
+}
+
+void amc::resetClocks::operator()() const
+{
+    // Step 1: Reset the external PLL
+    LOG4CPLUS_INFO(logger, "Reset the external PLL");
+    if (system("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0"))
+        throw std::runtime_error("Failed to reset the external PLL");
+
+    // Wait for the PLL to lock
+    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+
+    // Step 2: Reset the internal PLL
+    LOG4CPLUS_INFO(logger, "Reset the internal PLL");
+    utils::writeReg("GEM_AMC.TTC.CTRL.MMCM_RESET", 1);
+    for (size_t i = 0; i < 10; ++i) {
+        if (utils::readReg("GEM_AMC.TTC.STATUS.CLK.MMCM_LOCKED") == 1)
+            break;
+
+        if (i == 9)
+            throw std::runtime_error("Failed to reset the internal PLL");
+
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
+
+    // Step 3: Reset the FPGA logic after clock changes
+    utils::writeReg("GEM_AMC.GEM_SYSTEM.CTRL.GLOBAL_RESET", 1);
+    std::this_thread::sleep_for(std::chrono::milliseconds(50));
+
+    // Step 4: Align the clock phase to the TTC backplane clock
+    LOG4CPLUS_INFO(logger, "Align the clock phase to the TTC backplane clock");
 
-    //Write the phases
+    // Write the target phase
     const uint32_t targetPhase = 0x100;
     utils::writeReg("GEM_AMC.TTC.CTRL.LOCKMON_TARGET_PHASE", targetPhase);
     const uint32_t tollerancePhase = utils::readReg("GEM_AMC.TTC.CTRL.LOCKMON_TOLLERANCE");
@@ -211,16 +233,17 @@ void amc::recoverAMC::operator()() const
     } while ((utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") > targetPhase + tollerancePhase) || (utils::readReg("GEM_AMC.TTC.STATUS.CLK.PHASE_MONITOR.PHASE") < targetPhase - tollerancePhase));
     utils::writeReg("GEM_AMC.TTC.CTRL.CNT_RESET", 1);
 
-    //Reset GTHs
+    // Step 5: Reset the GTH transceivers
+    LOG4CPLUS_INFO(logger, "Reset the GTH transceivers");
     for (uint32_t i = 0; i < 64; i++) {
         const auto tmp = std::string { "GEM_AMC.OPTICAL_LINKS.MGT_CHANNEL_" } + std::to_string(i) + ".RESET";
-        utils::writeReg(tmp, 3);
+        utils::writeReg(tmp, 0x7);
     }
 
-    //Check GTHs status
+    // Check the GTH status
     LOG4CPLUS_INFO(logger, "GTHs status");
-    LOG4CPLUS_INFO(logger, "Ch # |  GTH Status  |    GTH Ctrl  ");
-    LOG4CPLUS_INFO(logger, " --------------------------------------------------------------------------------------------------");
+    LOG4CPLUS_INFO(logger, " Ch # |  GTH Status  |    GTH Ctrl  ");
+    LOG4CPLUS_INFO(logger, "------------------------------------");
 
     for (uint32_t i = 0; i < 64; i++) {
         const auto tmpStatus = std::string { "GEM_AMC.OPTICAL_LINKS.MGT_CHANNEL_" } + std::to_string(i) + ".STATUS";
@@ -228,10 +251,7 @@ void amc::recoverAMC::operator()() const
 
         LOG4CPLUS_INFO(logger, std::setw(6) << i << "  |  " << utils::readReg(tmpStatus) << "  |  " << utils::readReg(tmpCtrl));
     }
-    LOG4CPLUS_INFO(logger, " --------------------------------------------------------------------------------------------------");
-    LOG4CPLUS_INFO(logger, "Load OH FW to the RAM for promless progamming");
-    if (system("sh -c 'source /mnt/persistent/gemdaq/gemloader/gemloader_configure.sh'"))
-        throw std::runtime_error("Failed to source /mnt/persistent/gemdaq/gemloader/gemloader_configure.sh");
+    LOG4CPLUS_INFO(logger, "------------------------------------");
 }
 
 std::map<std::string, uint32_t> amc::repeatedRegRead::operator()(const std::vector<std::string>& regList, const bool& breakOnFailure, const uint32_t& nReads) const
@@ -275,6 +295,7 @@ void module_init(ModuleManager* modmgr)
     xhal::server::registerMethod<amc::sbitReadOut>(modmgr);
     xhal::server::registerMethod<amc::repeatedRegRead>(modmgr);
     xhal::server::registerMethod<amc::recoverAMC>(modmgr);
+    xhal::server::registerMethod<amc::resetClocks>(modmgr);
 
     // DAQ module methods (from amc/daq)
     xhal::server::registerMethod<amc::daq::enableDAQLink>(modmgr);
-- 
GitLab


From 4430f79c41c4d2d4815d6d79889b23ffa176f2e1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Sun, 4 Oct 2020 17:22:24 +0200
Subject: [PATCH 13/19] Attemp to check the GBT lock 20 times before
 programming

---
 gemhardware/devices/src/amc/HwGenericAMC.cpp | 21 ++++++++++++++++++--
 1 file changed, 19 insertions(+), 2 deletions(-)

diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index a1737a27..79c8463e 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -6,10 +6,12 @@
 #include <gem/rpc/daq_monitor.h>
 #include <gem/rpc/gbt.h>
 
+#include <chrono>
 #include <fstream>
 #include <iomanip>
 #include <numeric>
 #include <string>
+#include <thread>
 #include <vector>
 
 gem::hardware::amc::HwGenericAMC::HwGenericAMC(std::string const& amcDevice)
@@ -701,8 +703,23 @@ uint32_t gem::hardware::amc::HwGenericAMC::getGBTStatus()
 
 uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32_t optohybridMask)
 {
-    // Use only the working OptoHybrids
-    optohybridMask = getGBTStatus() & optohybridMask;
+    // Check the GBT status before programming
+    for (size_t i = 0; i < 20; ++i) {
+        const uint32_t gbtStatus = getGBTStatus();
+        if ((gbtStatus & optohybridMask) == optohybridMask)
+            break; // All good!
+
+        const std::string msg = toolbox::toString("Valid links (%d) different than expectations (%d) before programming GBT.", gbtStatus, optohybridMask);
+        CMSGEMOS_WARN(msg);
+
+        // Continue with the working OptoHybrids only
+        if (i == 19) {
+            optohybridMask = gbtStatus & optohybridMask;
+        }
+
+        // Let the GBT some time to lock
+        std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    }
 
     // Call the configureGBTs RPC method for the GBT configuration, i.e. using the configuration files stored on the AMC
     for (size_t i = 0; i < ::amc::OH_PER_AMC; i++) {
-- 
GitLab


From 23f06776932adff4a04ec24eccec41f67f53a14a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Sun, 4 Oct 2020 13:00:04 +0200
Subject: [PATCH 14/19] Check the SCA status after module reset

---
 gemrpc/src/amc/sca.cpp | 26 +++++++++++++++++++++++++-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/gemrpc/src/amc/sca.cpp b/gemrpc/src/amc/sca.cpp
index 15e4a903..47d2aba5 100644
--- a/gemrpc/src/amc/sca.cpp
+++ b/gemrpc/src/amc/sca.cpp
@@ -7,8 +7,10 @@
 #include <gem/rpc/hw_constants.h>
 #include <gem/rpc/utils.h>
 
+#include <chrono>
 #include <sstream>
 #include <string>
+#include <thread>
 #include <vector>
 
 namespace amc {
@@ -213,12 +215,34 @@ void amc::sca::resetSCASEUCounter::operator()(const uint16_t& ohMask) const
 void amc::sca::scaModuleReset::operator()(const uint16_t& ohMask) const
 {
     // Does this need to be protected, or do all versions of FW have this register?
-    uint32_t origMask = utils::readReg("GEM_AMC.SLOW_CONTROL.SCA.CTRL.SCA_RESET_ENABLE_MASK");
+    const uint32_t origMask = utils::readReg("GEM_AMC.SLOW_CONTROL.SCA.CTRL.SCA_RESET_ENABLE_MASK");
     utils::writeReg("GEM_AMC.SLOW_CONTROL.SCA.CTRL.SCA_RESET_ENABLE_MASK", ohMask);
 
     // Send the reset
     utils::writeReg("GEM_AMC.SLOW_CONTROL.SCA.CTRL.MODULE_RESET", 0x1);
 
+    // Check the SCA statuses
+    const uint32_t ready = utils::readReg("GEM_AMC.SLOW_CONTROL.SCA.STATUS.READY");
+    const uint32_t critical_error = utils::readReg("GEM_AMC.SLOW_CONTROL.SCA.STATUS.CRITICAL_ERROR");
+
+    if (((ready & ohMask) != ohMask) || ((critical_error & ohMask) != 0)) {
+        std::stringstream errmsg;
+        errmsg << std::hex << "SCA reset failed for some OH: ohMask: 0x" << ohMask << " - ready flags: 0x" << ready << " - crital error flags: 0x" << critical_error;
+        throw std::runtime_error(errmsg.str());
+    }
+
+    for (size_t i = 0; i < amc::OH_PER_AMC; ++i) {
+        if (!((ohMask >> i) & 0x1))
+            continue;
+
+        const auto tmpStatus = std::string { "GEM_AMC.SLOW_CONTROL.SCA.STATUS.NOT_READY_CNT_OH" } + std::to_string(i);
+        if (utils::readReg(tmpStatus) != 2) {
+            std::stringstream errmsg;
+            errmsg << std::hex << "SCA reset failed for some OH" << i << ": not ready counter different than 2";
+            throw std::runtime_error(errmsg.str());
+        }
+    }
+
     utils::writeReg("GEM_AMC.SLOW_CONTROL.SCA.CTRL.SCA_RESET_ENABLE_MASK", origMask);
 }
 
-- 
GitLab


From 4ec04617f14550b27c8ecb12631189381affd397 Mon Sep 17 00:00:00 2001
From: Camilla Galloni <camilla.galloni@cern.ch>
Date: Sun, 4 Oct 2020 12:52:29 +0200
Subject: [PATCH 15/19] Wait for TTC hard reset completion during configuration

---
 gemhardware/devices/src/amc/HwGenericAMC.cpp | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index 79c8463e..4ebf399e 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -746,9 +746,14 @@ uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32
     }
     GEM_CATCH_RPC_ERROR("HwGenericAMC::establishFrontEndCommunication", gem::hardware::devices::exception::Exception);
 
-    // Program the OH FPGA
+    // Program the OH FPGA through a local TTC hard reset
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x1);
     writeReg("GEM_AMC.TTC.GENERATOR.SINGLE_HARD_RESET", 0x1);
+
+    // Wait for TTC hard reset completion
+    std::this_thread::sleep_for(std::chrono::milliseconds(350));
+
+    // Clean-up
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
     writeReg("GEM_AMC.GEM_SYSTEM.CTRL.LINK_RESET", 0x1);
 
-- 
GitLab


From f15769cac3ca53a95e6103d1c3e7c4bae8770c4c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Sun, 4 Oct 2020 19:23:54 +0200
Subject: [PATCH 16/19] Check the GEM loader counters after OH FPGA programming

---
 gemhardware/devices/src/amc/HwGenericAMC.cpp | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/gemhardware/devices/src/amc/HwGenericAMC.cpp b/gemhardware/devices/src/amc/HwGenericAMC.cpp
index 4ebf399e..ceea63ba 100644
--- a/gemhardware/devices/src/amc/HwGenericAMC.cpp
+++ b/gemhardware/devices/src/amc/HwGenericAMC.cpp
@@ -746,6 +746,11 @@ uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32
     }
     GEM_CATCH_RPC_ERROR("HwGenericAMC::establishFrontEndCommunication", gem::hardware::devices::exception::Exception);
 
+    // Get the GEM_LOADER counters
+    const uint16_t gemloader_request_counter = readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_REQUEST_CNT");
+    const uint16_t gemloader_success_counter = readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_SUCCESS_CNT");
+    const uint16_t gemloader_failure_counter = readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_FAIL_CNT");
+
     // Program the OH FPGA through a local TTC hard reset
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x1);
     writeReg("GEM_AMC.TTC.GENERATOR.SINGLE_HARD_RESET", 0x1);
@@ -757,6 +762,12 @@ uint32_t gem::hardware::amc::HwGenericAMC::establishFrontEndCommunication(uint32
     writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
     writeReg("GEM_AMC.GEM_SYSTEM.CTRL.LINK_RESET", 0x1);
 
+    if ((gemloader_request_counter + 1 != readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_REQUEST_CNT")) || (gemloader_success_counter + 1 != readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_SUCCESS_CNT")) || (gemloader_failure_counter != readReg("GEM_AMC.GEM_SYSTEM.GEM_LOADER.LOAD_FAIL_CNT"))) {
+        const std::string msg = "GEM_LOADER failed!";
+        CMSGEMOS_ERROR(msg);
+        XCEPT_RAISE(gem::hardware::devices::exception::Exception, msg);
+    }
+
     return optohybridMask;
 }
 
-- 
GitLab


From f7451ecbbfe9f201917736b6f9b1c01f8ed9405c Mon Sep 17 00:00:00 2001
From: Camilla Galloni <camilla.galloni@cern.ch>
Date: Sun, 4 Oct 2020 18:22:45 +0200
Subject: [PATCH 17/19] Use TTC calibration mode from AMC for latency scan

---
 doc/examples/xml/gem904daq04.xml        | 18 ++++++------
 gembase/src/GEMApplication.cpp          |  3 +-
 gemcalibration/interface/Calibration.h  |  9 +++---
 gemhardware/managers/src/AMCManager.cpp | 38 ++++++++++++++++---------
 gemrpc/src/gbt.cpp                      |  2 +-
 5 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/doc/examples/xml/gem904daq04.xml b/doc/examples/xml/gem904daq04.xml
index a59a1e7d..cbe52d40 100644
--- a/doc/examples/xml/gem904daq04.xml
+++ b/doc/examples/xml/gem904daq04.xml
@@ -93,15 +93,15 @@
             <OC0_MASK xsi:type="xsd:unsignedInt">0x01</OC0_MASK>
           </AMC13TTCConfig>
 
-          <BGOConfig xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[4]">
-            <BGOInfo xsi:type="soapenc:Struct" soapenc:position="0">
-              <BGOChannel xsi:type="xsd:integer">0</BGOChannel>
-              <BGOcmd xsi:type="xsd:unsignedInt">0x14</BGOcmd>
-              <BGObx xsi:type="xsd:unsignedInt">450</BGObx> <!--450 default should be 50 after the bx of L1A, that forL1Amode=1 happens at 500-->
-              <BGOprescale xsi:type="xsd:unsignedInt">0x1</BGOprescale>
-              <BGOrepeat xsi:type="xsd:boolean">true</BGOrepeat>
-            </BGOInfo>
-          </BGOConfig>
+          <!-- <BGOConfig xsi:type="soapenc:Array" soapenc:arrayType="xsd:ur-type[4]"> -->
+          <!--    <BGOInfo xsi:type="soapenc:Struct" soapenc:position="0"> -->
+          <!--      <BGOChannel xsi:type="xsd:integer">0</BGOChannel> -->
+          <!--      <BGOcmd xsi:type="xsd:unsignedInt">0x14</BGOcmd> -->
+          <!--      <BGObx xsi:type="xsd:unsignedInt">450</BGObx> <!-1- 450 default should be 50 after the bx of L1A, that forL1Amode=1 happens at 500 --> -->
+          <!--      <BGOprescale xsi:type="xsd:unsignedInt">0x1</BGOprescale> -->
+          <!--      <BGOrepeat xsi:type="xsd:boolean">true</BGOrepeat> -->
+          <!--    </BGOInfo> -->
+          <!--  </BGOConfig> -->
 
           <PrescaleFactor xsi:type="xsd:integer">1</PrescaleFactor>
           <BCOffset xsi:type="xsd:integer">1</BCOffset>
diff --git a/gembase/src/GEMApplication.cpp b/gembase/src/GEMApplication.cpp
index 810b711e..15366a07 100644
--- a/gembase/src/GEMApplication.cpp
+++ b/gembase/src/GEMApplication.cpp
@@ -308,7 +308,6 @@ xoap::MessageReference gem::base::GEMApplication::calibParamRetrieve(xoap::Messa
 
     m_scanInfo.bag.scanType = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "calType");
     m_scanInfo.bag.scanMin = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "scanMin");
-    ;
     m_scanInfo.bag.scanMax = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "scanMax");
     m_scanInfo.bag.stepSize = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "stepSize");
     m_scanInfo.bag.nTriggers = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "nSamples"); ///TODO: change it everywhere?
@@ -320,7 +319,7 @@ xoap::MessageReference gem::base::GEMApplication::calibParamRetrieve(xoap::Messa
     m_scanInfo.bag.signalSourceType = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "signalSourceType");
     m_scanInfo.bag.pulseDelay = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "pulseDelay");
     m_scanInfo.bag.latency = gem::utils::soap::GEMSOAPToolBox::extractSOAPCommandParameterInteger(msg, "latency");
-    m_scanInfo.bag.calMode = (xdata::Boolean) false; // TODO: implement the selection in the calubration suite web interface
+    m_scanInfo.bag.calMode = (xdata::Boolean) false; // TODO: implement the selection in the calibration suite web interface
 
     return gem::utils::soap::GEMSOAPToolBox::makeSOAPReply(commandName, "CalibrationParametersRetrieved");
 }
diff --git a/gemcalibration/interface/Calibration.h b/gemcalibration/interface/Calibration.h
index 514bcbfa..a4c4ffac 100644
--- a/gemcalibration/interface/Calibration.h
+++ b/gemcalibration/interface/Calibration.h
@@ -66,14 +66,13 @@ namespace calibration {
                         } },
             { LATENCY, {
                            { "nSamples", "100" },
-                           { "trigType", "0" },
                            { "l1aTime", "250" },
                            { "mspl", "4" },
                            { "scanMin", "0" },
                            { "scanMax", "300" }, //"1023"},
                            { "vfatChMin", "0" },
                            { "vfatChMax", "1" },
-                           //{"vt2"       , 100},// TODO:need to be taken from DB
+                           // {"vt2"       , 100},// TODO:need to be taken from DB
                            // {"trigThrottle"  ,"0"},
                            { "signalSourceType", "0" },
                            { "pulseDelay", "0" }, //40
@@ -81,7 +80,7 @@ namespace calibration {
                        } },
             { SCURVE, {
                           { "nSamples", "100" },
-                          //{"trigType"  , "0"}, // TODO: TTC local should be only possible one
+                          // {"trigType"  , "0"}, // TODO: TTC local should be only possible one
                           { "l1aTime", "250" },
                           { "pulseDelay", "40" },
                           { "latency", "33" },
@@ -121,7 +120,7 @@ namespace calibration {
                          } },
             { CALIBRATEARMDAC, {
                                    { "nSamples", "100" },
-                                   //  {"trigType"  , "0"}, // TODO: TTC local should be only possible one
+                                   // {"trigType"  , "0"}, // TODO: TTC local should be only possible one
                                    { "l1aTime", "250" },
                                    { "pulseDelay", "40" },
                                    { "latency", "33" },
@@ -137,7 +136,7 @@ namespace calibration {
         ///  map of the parameters for which radio selector are used with relative viable options
 
         std::map<std::string, scanParamsRadioSelector> m_scanParamsRadioSelector {
-            { "trigType", { "TriggerType", { "TTC input", "Loopback", "Lemo/T3" } } },
+            { "trigType", { "TriggerType", { "Loopback", "TTC input", "Lemo/T3" } } },
             { "signalSourceType", { "Signal Source", { "Calibration Pulse", "Particle" } } },
             { "comparatorType", { "Coparator Type", { "CDF", "Arming comparator" } } },
             { "adcType", { "VFAT ADC reference", { "Internal", "External" } } },
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index b0f9eec0..5348c5d1 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -161,8 +161,15 @@ void gem::hardware::AMCManager::configureAction()
 
         // taken from Brian's macro
         m_amc->writeReg("GEM_AMC.TTC.GENERATOR.ENABLE", 0x0);
+
+        m_amc->writeReg("GEM_AMC.TTC.CTRL.CALPULSE_L1A_DELAY", 0x0);
         m_amc->writeReg("GEM_AMC.TTC.CTRL.CALIBRATION_MODE", 0x0);
 
+        if (m_scanInfo.bag.signalSourceType.value_ == 0) { // use calibration pulse from the TTC internally generated in the AMC
+            m_amc->writeReg("GEM_AMC.TTC.CTRL.CALPULSE_L1A_DELAY", 50); // send the L1A N BX after the calibration pulse
+            m_amc->writeReg("GEM_AMC.TTC.CTRL.CALIBRATION_MODE", 0x1);
+        }
+
         CMSGEMOS_INFO("AMCManager::configureAction:: exiting latency");
 
     } else if (m_scanInfo.bag.scanType.value_ == 3) {
@@ -201,7 +208,7 @@ void gem::hardware::AMCManager::configureAction()
 
         // Calibration
         if (m_scanInfo.bag.scanType.value_ == 2) {
-            //TODO:set calibration mode (atm set to false)
+            //TODO:set calibration mode (atm set to false) data format
             if (m_scanInfo.bag.calMode.value_)
                 optohybrid->configureOHCalDataFormat(vfatMask);
 
@@ -211,20 +218,23 @@ void gem::hardware::AMCManager::configureAction()
 
             if (m_scanInfo.bag.signalSourceType.value_ < 1) { //CG: Cal pulse
                 optohybrid->broadcastWrite("CFG_CAL_MODE", 0x1, vfatMask, false);
-            } ///for latency scans use the Voltage pulse(CAL_MODE 0x1), low CFG_CAL_DAC is a high injected charge amount
-            optohybrid->broadcastWrite("CFG_CAL_DAC", 6, vfatMask, false);
-            CMSGEMOS_DEBUG("AMCManager::configureAction: reading  specifics for latency on OH0VFAT23 MPSL " << m_scanInfo.bag.mspl.value_ << " reg " << optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_PULSE_STRETCH") << " CAL_DAC " << (uint32_t)optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_CAL_DAC"));
-
-            // enabling and disabling calpulse for channels on vfat
-            for (int ch = 0; ch < 128; ++ch) {
-                char reg[100];
-                if (ch < m_scanInfo.bag.vfatChMin.value_ || ch > m_scanInfo.bag.vfatChMax.value_) {
-                    sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                    optohybrid->broadcastWrite(reg, 0, vfatMask, false);
-                } else {
-                    sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                    optohybrid->broadcastWrite(reg, 1, vfatMask, false);
+                ///for latency scans with calibration pulse use the Voltage pulse(CAL_MODE 0x1), low CFG_CAL_DAC is a high injected charge amount
+                optohybrid->broadcastWrite("CFG_CAL_DAC", 6, vfatMask, false);
+
+                // enabling and disabling calpulse for channels on vfat
+                for (int ch = 0; ch < 128; ++ch) {
+                    char reg[100];
+                    if (ch < m_scanInfo.bag.vfatChMin.value_ || ch > m_scanInfo.bag.vfatChMax.value_) {
+                        sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
+                        optohybrid->broadcastWrite(reg, 0, vfatMask, false);
+                    } else {
+                        sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
+                        optohybrid->broadcastWrite(reg, 1, vfatMask, false);
+                    }
                 }
+                CMSGEMOS_DEBUG("OptoHybridManager::configureAction: reading  specifics for latency on OH0VFAT23 MPSL " << m_scanInfo.bag.mspl.value_ << " reg " << optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_PULSE_STRETCH") << " CAL_DAC " << (uint32_t)optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_CAL_DAC"));
+            } else { // For physical particle signal disable the CFG_CAL_MODE
+                optohybrid->broadcastWrite("CFG_CAL_MODE", 0x0, vfatMask, false);
             }
 
             CMSGEMOS_INFO("AMCManager::configureAction: ending  specifics for latency ");
diff --git a/gemrpc/src/gbt.cpp b/gemrpc/src/gbt.cpp
index 072ab433..af5278f2 100644
--- a/gemrpc/src/gbt.cpp
+++ b/gemrpc/src/gbt.cpp
@@ -198,7 +198,7 @@ void gbt::configureGBTs::operator()(const uint32_t& ohN) const
                 break;
         }
         if (gbtIndex != CONFIG_SIZE) {
-            throw std::range_error("GBT config size doesn't correspond to the expected one");
+            throw std::range_error("GBT config size doesn't correspond to the expected one: size is " + std::to_string(gbtIndex));
         }
         writeGBTConfig {}(ohN, j, gbtConfig);
     }
-- 
GitLab


From db3a67a2ac19fd825d1f8e4c9fc79b317d3b65a4 Mon Sep 17 00:00:00 2001
From: Camilla Galloni <camilla.galloni@cern.ch>
Date: Wed, 7 Oct 2020 11:56:00 +0200
Subject: [PATCH 18/19] Use RPC method confCalPulse to disable calibration
 pulses of VFAT channels

---
 .../interface/optohybrid/HwOptoHybrid.h       |  9 +++-
 .../devices/src/optohybrid/HwOptoHybrid.cpp   | 10 +++++
 gemhardware/managers/src/AMCManager.cpp       | 44 +++++++++----------
 gemrpc/interface/calibration_routines.h       |  2 +-
 gemrpc/src/calibration_routines.cpp           |  4 +-
 5 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/gemhardware/devices/interface/optohybrid/HwOptoHybrid.h b/gemhardware/devices/interface/optohybrid/HwOptoHybrid.h
index 5ae213b9..382fae68 100644
--- a/gemhardware/devices/interface/optohybrid/HwOptoHybrid.h
+++ b/gemhardware/devices/interface/optohybrid/HwOptoHybrid.h
@@ -348,7 +348,14 @@ namespace hardware {
             void configureAllGBTs(uint32_t const* gbtcfg); // FIXME, make private
             void configureAllGBTs(std::array<const uint32_t, 3 * 92> const& gbtcfg);
 
-        protected:
+            /// @brief Configures the VFATs in the VFAT mask for the calibration pulses, toggles the calibration mode, enables or desables the channels, enables the voltage or current pulse and applies a scale factor.
+            /// @param ohN is the OH number
+            /// @param vfatMask is the mask of the VFAT to be used
+            /// @param ch can be a specific channel between 0 and 127, 128 stands for all the channels
+            /// @param toffleOs is a boolean to enable (disable) the calibration pulse to the VFAT channels
+            /// @param calScaleFactos is a parameter to apply a scale factor to the current pulse
+            void confCalPulse(const uint16_t& ohN, const uint32_t& vfatMask, const uint32_t& ch, const bool& toggleOn, const bool& currentPulse, const uint32_t& calScaleFactor);
+
         private:
             // Do not use default constructor. HwOptoHybrid object should only be made using
             // either connection file method or with a list of URIs and address tables
diff --git a/gemhardware/devices/src/optohybrid/HwOptoHybrid.cpp b/gemhardware/devices/src/optohybrid/HwOptoHybrid.cpp
index c5a86065..469e3044 100644
--- a/gemhardware/devices/src/optohybrid/HwOptoHybrid.cpp
+++ b/gemhardware/devices/src/optohybrid/HwOptoHybrid.cpp
@@ -5,6 +5,7 @@
 #include <iomanip>
 
 #include "gem/hardware/devices/optohybrid/HwOptoHybrid.h"
+#include <gem/rpc/calibration_routines.h>
 #include <gem/rpc/gbt.h>
 #include <gem/rpc/optohybrid.h>
 #include <gem/rpc/vfat3.h>
@@ -34,6 +35,7 @@ void gem::hardware::optohybrid::HwOptoHybrid::connectRPC(bool reconnect)
         this->loadModule("optohybrid", "optohybrid v1.0.1");
         this->loadModule("vfat3", "vfat3 v1.0.1");
         this->loadModule("gbt", "gbt v1.0.1");
+        this->loadModule("calibration_routines", "calibration_routines v1.0.1");
         CMSGEMOS_DEBUG("HwOptoHybrid::connectRPC modules loaded");
     } else {
         // FIXME, should we throw? fail?
@@ -512,3 +514,11 @@ void gem::hardware::optohybrid::HwOptoHybrid::resetTTCCount(uint8_t const& signa
 
     // CTP7 module candidate?
 }
+
+void gem::hardware::optohybrid::HwOptoHybrid::confCalPulse(const uint16_t& ohN, const uint32_t& vfatMask, const uint32_t& ch, const bool& toggleOn, const bool& currentPulse, const uint32_t& calScaleFactor)
+{
+    try {
+        xhal::client::call<::calibration::confCalPulse>(rpc, ohN, vfatMask, ch, toggleOn, currentPulse, calScaleFactor);
+    }
+    GEM_CATCH_RPC_ERROR("HwOptoHybrid::confCalPulse", gem::hardware::devices::exception::Exception);
+}
diff --git a/gemhardware/managers/src/AMCManager.cpp b/gemhardware/managers/src/AMCManager.cpp
index 5348c5d1..60d9e0fc 100644
--- a/gemhardware/managers/src/AMCManager.cpp
+++ b/gemhardware/managers/src/AMCManager.cpp
@@ -151,12 +151,12 @@ void gem::hardware::AMCManager::configureAction()
         uint32_t runParams = ((0x1 << 22) | (0x0 << 21) | (0x6 << 13) | ((m_scanInfo.bag.mspl.value_ & 0x7) << 10) | (m_scanInfo.bag.scanMin.value_ & 0x3ff));
         //                       isExtTrig; isCurrentPulse; CFG_CAL_DAC;   MSPL/\;
 
-        CMSGEMOS_INFO("AMCManager::configureAction AMC runParams :" << runParams); //CG: TO be removed
+        CMSGEMOS_INFO("AMCManager::configureAction: AMC runParams: " << runParams); //CG: TO be removed
         m_amc->setDAQLinkRunParameters(runParams);
-        CMSGEMOS_INFO("AMCManager::configureAction::  m_scanInfo.bag.calMode.value_ " << m_scanInfo.bag.calMode.value_); ///CG remove
 
         // If calibration format mode invoked for data
         // setting caldata format here; and in OHmanager set the channels for the calmode
+        CMSGEMOS_INFO("AMCManager::configureAction: m_scanInfo.bag.calMode.value_: " << m_scanInfo.bag.calMode.value_); ///CG remove
         m_amc->configureAMCCalDataFormat(m_scanInfo.bag.calMode.value_);
 
         // taken from Brian's macro
@@ -169,13 +169,10 @@ void gem::hardware::AMCManager::configureAction()
             m_amc->writeReg("GEM_AMC.TTC.CTRL.CALPULSE_L1A_DELAY", 50); // send the L1A N BX after the calibration pulse
             m_amc->writeReg("GEM_AMC.TTC.CTRL.CALIBRATION_MODE", 0x1);
         }
-
-        CMSGEMOS_INFO("AMCManager::configureAction:: exiting latency");
-
     } else if (m_scanInfo.bag.scanType.value_ == 3) {
         uint32_t initialVT1 = m_scanInfo.bag.scanMin.value_;
         uint32_t initialVT2 = 0; // std::max(0,(uint32_t)m_scanInfo.bag.scanMax.value_);
-        CMSGEMOS_INFO("AMCManager::configureAction FIRST VT1 " << initialVT1 << " VT2 " << initialVT2);
+        CMSGEMOS_INFO("AMCManager::configureAction: FIRST VT1 " << initialVT1 << " VT2 " << initialVT2);
 
         m_amc->setDAQLinkRunType(0x3);
         // m_amc->setDAQLinkRunParameter(0x1,latency);  // set this at start so DQM has it?
@@ -207,38 +204,35 @@ void gem::hardware::AMCManager::configureAction()
         optohybrid->configureVFATs();
 
         // Calibration
+        CMSGEMOS_INFO("AMCManager::configureAction: beginning specifics for latency");
+
         if (m_scanInfo.bag.scanType.value_ == 2) {
             //TODO:set calibration mode (atm set to false) data format
             if (m_scanInfo.bag.calMode.value_)
                 optohybrid->configureOHCalDataFormat(vfatMask);
 
-            CMSGEMOS_DEBUG("AMCManager::configureAction configureAction: Latency scan with value " << m_scanInfo.bag.scanMin.value_);
+            CMSGEMOS_DEBUG("AMCManager::configureAction: Latency scan with value " << m_scanInfo.bag.scanMin.value_);
             optohybrid->broadcastWrite("CFG_LATENCY", m_scanInfo.bag.scanMin.value_, vfatMask, false);
             optohybrid->broadcastWrite("CFG_PULSE_STRETCH", m_scanInfo.bag.mspl.value_, vfatMask, false);
 
-            if (m_scanInfo.bag.signalSourceType.value_ < 1) { //CG: Cal pulse
+            if (m_scanInfo.bag.signalSourceType.value_ < 1) { // Calibration pulses
+                // Disable the calibration module and the calibration pulses for all channels
+                optohybrid->confCalPulse(link, vfatMask, 128, false, false, 0);
+
+                // Use voltage pulses (CAL_MODE == 0x1)
+                // Note that a low CFG_CAL_DAC corresponds to a high injected charge
                 optohybrid->broadcastWrite("CFG_CAL_MODE", 0x1, vfatMask, false);
-                ///for latency scans with calibration pulse use the Voltage pulse(CAL_MODE 0x1), low CFG_CAL_DAC is a high injected charge amount
                 optohybrid->broadcastWrite("CFG_CAL_DAC", 6, vfatMask, false);
 
-                // enabling and disabling calpulse for channels on vfat
-                for (int ch = 0; ch < 128; ++ch) {
-                    char reg[100];
-                    if (ch < m_scanInfo.bag.vfatChMin.value_ || ch > m_scanInfo.bag.vfatChMax.value_) {
-                        sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                        optohybrid->broadcastWrite(reg, 0, vfatMask, false);
-                    } else {
-                        sprintf(reg, "VFAT_CHANNELS.CHANNEL%i.CALPULSE_ENABLE", ch);
-                        optohybrid->broadcastWrite(reg, 1, vfatMask, false);
-                    }
-                }
+                // Enable only channel 0 on all VFAT
+                char reg[100];
+                optohybrid->broadcastWrite("VFAT_CHANNELS.CHANNEL0.CALPULSE_ENABLE", 1, vfatMask, false);
+
                 CMSGEMOS_DEBUG("OptoHybridManager::configureAction: reading  specifics for latency on OH0VFAT23 MPSL " << m_scanInfo.bag.mspl.value_ << " reg " << optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_PULSE_STRETCH") << " CAL_DAC " << (uint32_t)optohybrid->readReg("GEM_AMC.OH.OH0.GEB.VFAT23.CFG_CAL_DAC"));
-            } else { // For physical particle signal disable the CFG_CAL_MODE
+            } else { // Physical particle signal
+                // Disable the calibration module
                 optohybrid->broadcastWrite("CFG_CAL_MODE", 0x0, vfatMask, false);
             }
-
-            CMSGEMOS_INFO("AMCManager::configureAction: ending  specifics for latency ");
-
         } else if (m_scanInfo.bag.scanType.value_ == 3) { //S-curve
             // FIXME OBSOLETE
 
@@ -253,6 +247,8 @@ void gem::hardware::AMCManager::configureAction()
 
             uint32_t initialVT2 = 0; //std::max(0,(uint32_t)m_scanMax.value_);
         }
+
+        CMSGEMOS_INFO("AMCManager::configureAction: ending specifics for latency ");
     }
 
     CMSGEMOS_INFO("AMCManager::configureAction end");
diff --git a/gemrpc/interface/calibration_routines.h b/gemrpc/interface/calibration_routines.h
index 2153a37c..b69d76d7 100644
--- a/gemrpc/interface/calibration_routines.h
+++ b/gemrpc/interface/calibration_routines.h
@@ -68,7 +68,7 @@ const std::unordered_map<uint32_t, std::tuple<std::string, int, int>> vfat3DACAn
 struct confCalPulse : xhal::common::Method {
     void operator()(const uint16_t& ohN,
         const uint32_t& mask,
-        const uint8_t& ch,
+        const uint32_t& ch,
         const bool& toggleOn,
         const bool& currentPulse,
         const uint32_t& calScaleFactor) const;
diff --git a/gemrpc/src/calibration_routines.cpp b/gemrpc/src/calibration_routines.cpp
index ef85bcdb..d6170e28 100644
--- a/gemrpc/src/calibration_routines.cpp
+++ b/gemrpc/src/calibration_routines.cpp
@@ -46,14 +46,14 @@ void calibration::applyChanMask(const std::unordered_map<uint32_t, uint32_t>& ch
 
 void calibration::confCalPulse::operator()(const uint16_t& ohN,
     const uint32_t& vfatMask,
-    const uint8_t& ch,
+    const uint32_t& ch,
     const bool& toggleOn,
     const bool& currentPulse,
     const uint32_t& calScaleFactor) const
 {
     const uint32_t notmask = (~vfatMask) & 0xffffff;
 
-    if (ch >= 128) {
+    if (ch > 128) {
         std::stringstream errmsg;
         errmsg << "Invalid channel selection: " << ch << " > 128";
         LOG4CPLUS_ERROR(logger, errmsg.str());
-- 
GitLab


From dc6f083245985948e3fb9f40cebe92a3b55718e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laurent=20P=C3=A9tr=C3=A9?= <laurent.petre@cern.ch>
Date: Wed, 18 Nov 2020 18:46:19 +0100
Subject: [PATCH 19/19] Disable external PLL reset

Was leading to communication issues with the front-end. To be
investigated later.
---
 gemrpc/interface/amc.h |  2 +-
 gemrpc/src/amc.cpp     | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gemrpc/interface/amc.h b/gemrpc/interface/amc.h
index 9b4e320c..d40594d4 100644
--- a/gemrpc/interface/amc.h
+++ b/gemrpc/interface/amc.h
@@ -104,7 +104,7 @@ struct recoverAMC : public xhal::common::Method {
 
 /// @brief Resets all the AMC clocks
 ///
-/// * Reset the external PLL (Si5324)
+/// * Reset the external PLL (Si5324) [currently disabled]
 /// * Reset the internal PLL
 /// * Reset the FPGA logic after clock changes
 /// * Align the clock phase to the TTC backplane clock
diff --git a/gemrpc/src/amc.cpp b/gemrpc/src/amc.cpp
index eeb12409..c3ffb54e 100644
--- a/gemrpc/src/amc.cpp
+++ b/gemrpc/src/amc.cpp
@@ -194,12 +194,12 @@ void amc::recoverAMC::operator()() const
 void amc::resetClocks::operator()() const
 {
     // Step 1: Reset the external PLL
-    LOG4CPLUS_INFO(logger, "Reset the external PLL");
-    if (system("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0"))
-        throw std::runtime_error("Failed to reset the external PLL");
+    /* LOG4CPLUS_INFO(logger, "Reset the external PLL"); */
+    /* if (system("/bin/clockinit $GEM_PATH/scripts/clkA_ttc_in_160p32_320p64_out_BW_HIGH.txt 320_160 A0 A1 A1 A0")) */
+    /*     throw std::runtime_error("Failed to reset the external PLL"); */
 
-    // Wait for the PLL to lock
-    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
+    /* // Wait for the PLL to lock */
+    /* std::this_thread::sleep_for(std::chrono::milliseconds(1000)); */
 
     // Step 2: Reset the internal PLL
     LOG4CPLUS_INFO(logger, "Reset the internal PLL");
-- 
GitLab