LCOV - code coverage report
Current view: top level - mu2e-pcie-utils/cfoInterfaceLib - CFO_Registers.cpp (source / functions) Coverage Total Hit
Test: mu2edaq.info.cleaned Lines: 0.0 % 1743 0
Test Date: 2026-10-29 01:38:59 Functions: 0.0 % 252 0

            Line data    Source code
       1              : #include "cfoInterfaceLib/CFO_Registers.h"
       2              : 
       3              : #include <assert.h>
       4              : #include <unistd.h>
       5              : #include <chrono>
       6              : #include <cmath>
       7              : #include <iomanip>  // std::setw, std::setfill
       8              : #include <sstream>  // Convert uint to hex stLink
       9              : 
      10              : #include "artdaq-core/Utilities/ExceptionHandler.hh"    /*for artdaq::ExceptionHandler*/
      11              : #include "artdaq-core/Utilities/ExceptionStackTrace.hh" /*for artdaq::ExceptionStackTrace*/
      12              : #include "cfoInterfaceLib/CFO_Compiler.hh"
      13              : 
      14              : #include "TRACE/tracemf.h"
      15              : #define TLVL_ResetCFO TLVL_DEBUG + 5
      16              : #define TLVL_AutogenDRP TLVL_DEBUG + 6
      17              : #define TLVL_SERDESReset TLVL_DEBUG + 7
      18              : #define TLVL_CalculateFreq TLVL_DEBUG + 8
      19              : 
      20              : #include "dtcInterfaceLib/otsStyleCoutMacros.h"
      21              : 
      22              : #undef __COUT_HDR__
      23              : #define __COUT_HDR__ "CFO " << this->getDeviceUID() << ": "
      24              : 
      25            0 : CFOLib::CFO_Registers::CFO_Registers(DTC_SimMode mode, int cfo, std::string expectedDesignVersion,
      26            0 :                                                                          bool skipInit, const std::string& uid)
      27            0 :         : simMode_(mode), usingDetectorEmulator_(false), dmaSize_(16)
      28              : {
      29            0 :         TLOG(TLVL_INFO) << "CONSTRUCTOR";
      30              : 
      31            0 :         auto sim = getenv("CFOLIB_SIM_ENABLE");
      32            0 :         if (sim == nullptr)
      33              :         {
      34              :                 // Give priority to CFOLIB_SIM_ENABLE, but go ahead and check DTCLIB_SIM_ENABLE, too
      35            0 :                 sim = getenv("DTCLIB_SIM_ENABLE");
      36              :         }
      37            0 :         if (sim != nullptr)
      38              :         {
      39            0 :                 switch (sim[0])
      40              :                 {
      41            0 :                         case '1':
      42              :                         case 'e':
      43              :                         case 'E':
      44            0 :                                 simMode_ = DTC_SimMode_Tracker;  // sim enabled
      45            0 :                                 break;
      46            0 :                         case '2':
      47              :                         case 'l':
      48              :                         case 'L':
      49            0 :                                 simMode_ = DTC_SimMode_Loopback;
      50            0 :                                 break;
      51            0 :                         case '0':
      52              :                         default:
      53            0 :                                 simMode_ = DTC_SimMode_Disabled;
      54            0 :                                 break;
      55              :                 }
      56              :         }
      57              : 
      58            0 :         if (cfo == -1)
      59              :         {
      60            0 :                 auto CFOE = getenv("CFOLIB_CFO");
      61            0 :                 if (CFOE != nullptr)
      62              :                 {
      63            0 :                         cfo = atoi(CFOE);
      64              :                 }
      65              :                 else
      66              :                 {
      67            0 :                         CFOE = getenv("DTCLIB_DTC");  // Check both environment variables for CFO
      68            0 :                         if (CFOE != nullptr)
      69              :                         {
      70            0 :                                 cfo = atoi(CFOE);
      71              :                         }
      72              :                         else
      73              :                         {
      74            0 :                                 cfo = 0;
      75              :                         }
      76              :                 }
      77              :         }
      78              : 
      79            0 :         SetSimMode(expectedDesignVersion, simMode_, cfo, skipInit, (uid == "" ? ("CFO" + std::to_string(cfo)) : uid));
      80            0 : }  // end costructor()
      81              : 
      82            0 : CFOLib::CFO_Registers::~CFO_Registers()
      83              : {
      84            0 :         TLOG(TLVL_INFO) << "DESTRUCTOR";
      85            0 : }  // end destructor()
      86              : 
      87            0 : DTCLib::DTC_SimMode CFOLib::CFO_Registers::SetSimMode(std::string expectedDesignVersion, DTC_SimMode mode, int cfo,
      88              :                                                                                                           bool skipInit, const std::string& uid)
      89              : {
      90            0 :         simMode_ = mode;
      91              : 
      92            0 :         TLOG(TLVL_INFO) << "Initializing CFO device, sim mode is " << DTC_SimModeConverter(simMode_).toString() << " for uid = " << uid << ", deviceIndex = " << cfo;
      93              : 
      94            0 :         device_.init(simMode_, cfo, /* simMemoryFile */ "", uid);
      95            0 :         if (expectedDesignVersion != "")
      96              :         {
      97            0 :                 uint32_t parsedExpectedVersion = 0;
      98            0 :                 std::string parsedDesignDate = "";
      99              :                 try
     100              :                 {
     101            0 :                         parsedExpectedVersion = static_cast<uint32_t>(std::stoul(expectedDesignVersion, nullptr, 16));
     102            0 :                         parsedDesignDate = ReadDesignDate(parsedExpectedVersion);
     103              :                 }
     104            0 :                 catch (...)  // illegal/non-hex expectedDesignVersion
     105              :                 {
     106            0 :                         __SS__;
     107            0 :                         ss << "Version mismatch (is Expected Firmware Version string legal?)! Expected CFO (device index #" << cfo << ") version is '" << expectedDesignVersion << "' while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
     108            0 :                         __SS_THROW__;
     109            0 :                 }
     110              : 
     111            0 :                 if (parsedExpectedVersion != ReadRegister_(CFOandDTC_Register_DesignDate))
     112              :                 {
     113            0 :                         __SS__;
     114            0 :                         ss << "Version mismatch! Expected CFO (device index #" << cfo << ") version is '" << parsedDesignDate << "' (0x" << std::hex << parsedExpectedVersion << " != 0x" << ReadRegister_(CFOandDTC_Register_DesignDate) << ") while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
     115            0 :                         __SS_THROW__;
     116              :                         // throw new DTC_WrongVersionException(expectedDesignVersion, ReadDesignVersion());
     117            0 :                 }
     118            0 :         }
     119              : 
     120            0 :         if (skipInit)
     121              :         {
     122            0 :                 __COUT_INFO__ << "SKIPPING Initializing device";
     123            0 :                 return simMode_;
     124              :         }
     125              : 
     126            0 :         __COUT__ << "Initialize requested, setting device registers acccording to sim mode " << DTC_SimModeConverter(simMode_).toString();
     127              :         // Keep whatever links the hardware already has enabled; only normalize them to Tx+Rx
     128              :         // and make sure disabled links are out of loopback.
     129            0 :         for (auto link : CFO_Links)
     130              :         {
     131            0 :                 DTC_LinkEnableMode current = ReadLinkEnabled(link);
     132            0 :                 bool LinkEnabled = current.TransmitEnable || current.ReceiveEnable;
     133            0 :                 if (!LinkEnabled)
     134              :                 {
     135            0 :                         DisableLink(link);
     136            0 :                         SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
     137              :                 }
     138              :                 else
     139              :                 {
     140            0 :                         EnableLink(link, DTC_LinkEnableMode(true, true));
     141              :                 }
     142              :         }
     143              : 
     144            0 :         if (simMode_ != DTC_SimMode_Disabled)
     145              :         {
     146              :                 // Set up hardware simulation mode: Link 0 Tx/Rx Enabled, Loopback Enabled, ROC Emulator Enabled. All other Links
     147              :                 // disabled.
     148            0 :                 for (auto link : CFO_Links)
     149              :                 {
     150            0 :                         if (simMode_ == DTC_SimMode_Loopback)
     151              :                         {
     152            0 :                                 SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_NearPCS);
     153              :                                 //                      SetMaxROCNumber(CFO_Link_0, CFO_ROC_0);
     154              :                         }
     155              :                 }
     156              :                 // SetInternalSystemClock(); //RAR does not select clock to JA
     157            0 :                 DisableEmbeddedClockMarker();
     158              :         }
     159            0 :         ReadMinDMATransferLength();
     160              : 
     161            0 :         __COUT__ << "Done setting device registers";
     162            0 :         return simMode_;
     163              : }
     164              : 
     165            0 : bool CFOLib::CFO_Registers::ReadDDRFIFOEmpty(std::optional<uint32_t> val)
     166              : {
     167            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus);
     168            0 :         return data[2];
     169              : }
     170              : 
     171            0 : bool CFOLib::CFO_Registers::ReadDDRClockCalibrationDone(std::optional<uint32_t> val)
     172              : {
     173            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus);
     174            0 :         return data[0];
     175              : }
     176              : 
     177            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatDesignStatus()
     178              : {
     179            0 :         auto form = CreateFormatter(CFOandDTC_Register_DesignStatus);
     180            0 :         form.description = "Design Status Register";
     181            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     182            0 :         form.vals.push_back(std::string("DDR FIFO Empty:             [") + (ReadDDRFIFOEmpty(form.value) ? "x" : " ") + "]");
     183            0 :         form.vals.push_back(std::string("DDR Clock Calibration Done: [") + (ReadDDRClockCalibrationDone(form.value) ? "x" : " ") + "]");
     184            0 :         return form;
     185            0 : }
     186              : 
     187              : // RAR: Now just Soft Reset resets run plan
     188              : //  void CFOLib::CFO_Registers::ResetCFORunPlan()
     189              : //  {
     190              : //      TLOG(TLVL_ResetCFO) << __COUT_HDR__ << "SoftReset Run Plan start";
     191              : //      std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     192              : //      data[27] = 1;  // CFO Run Plan Reset bit
     193              : //      WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     194              : //      data[27] = 0;  // Restore CFO Run Plan Reset bit
     195              : //      WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     196              : //  }
     197              : 
     198              : // bool CFOLib::CFO_Registers::ReadResetCFORunPlan(std::optional<uint32_t> val)
     199              : // {
     200              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(CFOandDTC_Register_Control);
     201              : //      return dataSet[27];
     202              : // }
     203              : 
     204            0 : void CFOLib::CFO_Registers::EnableLED7()
     205              : {
     206            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     207            0 :         data[23] = 1;
     208            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     209            0 : }
     210              : 
     211            0 : void CFOLib::CFO_Registers::DisableReadLED7()
     212              : {
     213            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     214            0 :         data[23] = 0;
     215            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     216            0 : }
     217              : 
     218            0 : bool CFOLib::CFO_Registers::ReadLED7State(std::optional<uint32_t> val)
     219              : {
     220            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     221            0 :         return data[23];
     222              : }
     223              : 
     224            0 : void CFOLib::CFO_Registers::EnableAcceleratorRF0()
     225              : {
     226            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     227            0 :         data[2] = 1;
     228            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     229            0 : }
     230              : 
     231            0 : void CFOLib::CFO_Registers::DisableAcceleratorRF0()
     232              : {
     233            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     234            0 :         data[2] = 0;
     235            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     236            0 : }
     237              : 
     238            0 : bool CFOLib::CFO_Registers::ReadAcceleratorRF0Enable(std::optional<uint32_t> val)
     239              : {
     240            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     241            0 :         return data[2];
     242              : }
     243              : 
     244            0 : void CFOLib::CFO_Registers::EnableEmbeddedClockMarker()
     245              : {
     246            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     247            0 :         data[1] = 1;
     248            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     249            0 : }
     250              : 
     251            0 : void CFOLib::CFO_Registers::DisableEmbeddedClockMarker()
     252              : {
     253            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     254            0 :         data[1] = 0;
     255            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     256            0 : }
     257              : 
     258            0 : bool CFOLib::CFO_Registers::ReadEmbeddedClockMarkerEnable(std::optional<uint32_t> val)
     259              : {
     260            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     261            0 :         return data[1];
     262              : }
     263              : 
     264            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCFOControl()
     265              : {
     266            0 :         auto form = CreateFormatter(CFOandDTC_Register_Control);
     267            0 :         form.description = "CFO Control";
     268            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     269              :         // ~~~  CFO Control Register (0x9100) ~~~
     270              :         // Bit Position Mode    Default Value   Description
     271              :         // 31   RW      0b0     CFO Soft Reset (Self-clearing)
     272              :         // 30-28        RO      0x0     Reserved
     273              :         // 27   RW      0b0     DDR Write Reset
     274              :         // 26-24        RO      0x0     Reserved
     275              :         // 23   RW      0b0     Reserved (Formerly DRP Auto Generate Enable)
     276              :         // 22-17        RO      0x00    Reserved
     277              :         // 16   RW      0b0     Led 7
     278              :         // 15-10        RO      0x0000  Reserved
     279              :         // 9    RW      0b0     Punched Clock Enable
     280              :         // 8    RW      0b0     SERDES Global Reset
     281              :         // 7-4  RO      0x0000  Reserved
     282              :         // 3    RW      0b0     CFO Loopback Test Launch Control
     283              :         // 2    RW      0x0     Accelerator RF-0 Event Window Input Enable
     284              :         // 1    RW      0b0     Embedded Clock Marker Enable
     285              :         // 0    RO      0b0     CFO Hard Reset (Self-clearing)
     286              : 
     287            0 :         form.vals.push_back(std::string("Bit-31 CFO Soft Reset (Self-clearing):  [") + (ReadSoftReset(form.value) ? "x" : " ") + "]");
     288              :         // RAR: not just Soft Reset for resetting run plan
     289              :         // form.vals.push_back(std::string("Bit-27 CFO Run Plan Reset:              [") + (ReadResetCFORunPlan(form.value) ? "x" : " ") + "]");
     290            0 :         form.vals.push_back(std::string("Bit-16 LED 7:                           [") + (ReadLED7State(form.value) ? "x" : " ") + "]");
     291            0 :         form.vals.push_back(std::string("Bit-09 Punched Clock Enable:            [") + (CFOandDTC_Registers::ReadPunchEnable(form.value) ? "x" : " ") + "]");
     292            0 :         form.vals.push_back(std::string("Bit-08 SERDES Global Reset:             [") + (CFOandDTC_Registers::ReadResetSERDES(form.value) ? "x" : " ") + "]");
     293            0 :         form.vals.push_back(std::string("Bit-02 Accelerator RF-0 Input Enable:   [") + (ReadAcceleratorRF0Enable(form.value) ? "x" : " ") + "]");
     294            0 :         form.vals.push_back(std::string("Bit-01 Embedded Clock Marker Enable:    [") + (ReadEmbeddedClockMarkerEnable(form.value) ? "x" : " ") + "]");
     295            0 :         form.vals.push_back(std::string("Bit-00 CFO Hard Reset (Self-clearing):  [") + (ReadHardReset(form.value) ? "x" : " ") + "]");
     296            0 :         return form;
     297            0 : }
     298              : 
     299              : // DMA Transfer Length Register
     300            0 : void CFOLib::CFO_Registers::SetTriggerDMATransferLength(uint16_t length)
     301              : {
     302            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
     303            0 :         data = (data & 0x0000FFFF) + (length << 16);
     304            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
     305            0 : }
     306              : 
     307            0 : uint16_t CFOLib::CFO_Registers::ReadTriggerDMATransferLength(std::optional<uint32_t> val)
     308              : {
     309            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
     310            0 :         data >>= 16;
     311            0 :         return static_cast<uint16_t>(data);
     312              : }
     313              : 
     314            0 : void CFOLib::CFO_Registers::SetMinDMATransferLength(uint16_t length)
     315              : {
     316            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
     317            0 :         data = (data & 0xFFFF0000) + length;
     318            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
     319            0 : }
     320              : 
     321            0 : uint16_t CFOLib::CFO_Registers::ReadMinDMATransferLength(std::optional<uint32_t> val)
     322              : {
     323            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
     324            0 :         data = data & 0x0000FFFF;
     325            0 :         dmaSize_ = static_cast<uint16_t>(data);
     326            0 :         return dmaSize_;
     327              : }
     328              : 
     329            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatDMATransferLength()
     330              : {
     331            0 :         auto form = CreateFormatter(CFOandDTC_Register_DMATransferLength);
     332            0 :         form.description = "DMA Transfer Length";
     333            0 :         form.vals.push_back("");  // translation
     334            0 :         std::stringstream o;
     335            0 :         o << "Trigger Length: 0x" << std::hex << ReadTriggerDMATransferLength(form.value);
     336            0 :         form.vals.push_back(o.str());
     337            0 :         std::stringstream p;
     338            0 :         p << "Minimum Length: 0x" << std::hex << ReadMinDMATransferLength(form.value);
     339            0 :         form.vals.push_back(p.str());
     340            0 :         return form;
     341            0 : }
     342              : 
     343              : // SERDES Loopback Enable Register
     344            0 : void CFOLib::CFO_Registers::SetSERDESLoopbackMode(const CFO_Link_ID& link, const DTC_SERDESLoopbackMode& mode)
     345              : {
     346            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable);
     347            0 :         std::bitset<3> modeSet = mode;
     348            0 :         data[3 * link] = modeSet[0];
     349            0 :         data[3 * link + 1] = modeSet[1];
     350            0 :         data[3 * link + 2] = modeSet[2];
     351            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_LoopbackEnable);
     352            0 : }
     353              : 
     354            0 : DTCLib::DTC_SERDESLoopbackMode CFOLib::CFO_Registers::ReadSERDESLoopback(const CFO_Link_ID& link, std::optional<uint32_t> val)
     355              : {
     356            0 :         std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable)) >> (3 * link);
     357            0 :         return static_cast<DTC_SERDESLoopbackMode>(dataSet.to_ulong());
     358              : }
     359              : 
     360            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESLoopbackEnable()
     361              : {
     362            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
     363            0 :         form.description = "SERDES Loopback Enable";
     364            0 :         form.vals.push_back("");  // translation
     365            0 :         for (auto r : CFO_Links)
     366            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " +
     367            0 :                                                         DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(r, form.value)).toString());
     368            0 :         return form;
     369            0 : }
     370              : 
     371              : // Clock Status Register
     372            0 : bool CFOLib::CFO_Registers::ReadSERDESOscillatorIICError(std::optional<uint32_t> val)
     373              : {
     374            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
     375            0 :         return dataSet[2];
     376              : }
     377              : 
     378            0 : bool CFOLib::CFO_Registers::ReadSERDESOscillatorInitializationComplete(std::optional<uint32_t> val)
     379              : {
     380            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
     381            0 :         return dataSet[1];
     382              : }
     383              : 
     384            0 : bool CFOLib::CFO_Registers::WaitForSERDESOscillatorInitializationComplete(double max_wait)
     385              : {
     386            0 :         auto start_time = std::chrono::steady_clock::now();
     387            0 :         while (
     388            0 :                 !ReadSERDESOscillatorInitializationComplete() &&
     389            0 :                 std::chrono::duration_cast<std::chrono::duration<double>>(std::chrono::steady_clock::now() - start_time).count() <
     390              :                         max_wait)
     391              :         {
     392            0 :                 usleep(1000);
     393              :         }
     394            0 :         return ReadSERDESOscillatorInitializationComplete();
     395              : }
     396              : 
     397            0 : bool CFOLib::CFO_Registers::ReadTimingClockPLLLocked(std::optional<uint32_t> val)
     398              : {
     399            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
     400            0 :         return dataSet[0];
     401              : }
     402              : 
     403            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatClockOscillatorStatus()
     404              : {
     405            0 :         auto form = CreateFormatter(CFOandDTC_Register_ClockOscillatorStatus);
     406            0 :         form.description = "Clock Oscillator Status";
     407            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     408            0 :         form.vals.push_back(std::string("SERDES IIC Error:      [") + (ReadSERDESOscillatorIICError(form.value) ? "x" : " ") + "]");
     409            0 :         form.vals.push_back(std::string("SERDES Init.Complete:  [") +
     410            0 :                                                 (ReadSERDESOscillatorInitializationComplete(form.value) ? "x" : " ") + "]");
     411            0 :         form.vals.push_back(std::string("Timing Clock PLL Lock: [") + (ReadTimingClockPLLLocked(form.value) ? "x" : " ") + "]");
     412            0 :         return form;
     413            0 : }
     414              : 
     415              : // Link Enable Register
     416            0 : void CFOLib::CFO_Registers::EnableLink(const CFO_Link_ID& link, const DTC_LinkEnableMode& mode)
     417              : {
     418            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
     419            0 :         if (link == CFO_Link_ALL)
     420              :         {
     421            0 :                 for (uint8_t i = 0; i < 8; ++i)
     422              :                 {
     423            0 :                         data[i] = mode.TransmitEnable;
     424            0 :                         data[i + 8] = mode.ReceiveEnable;
     425              :                 }
     426              :         }
     427              :         else
     428              :         {
     429            0 :                 data[link] = mode.TransmitEnable;
     430            0 :                 data[link + 8] = mode.ReceiveEnable;
     431              :         }
     432            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
     433            0 : }
     434              : 
     435            0 : void CFOLib::CFO_Registers::DisableLink(const CFO_Link_ID& link, const DTC_LinkEnableMode& mode)
     436              : {
     437            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
     438            0 :         data[link] = data[link] && !mode.TransmitEnable;
     439            0 :         data[link + 8] = data[link + 8] && !mode.ReceiveEnable;
     440            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
     441            0 : }
     442              : 
     443            0 : DTCLib::DTC_LinkEnableMode CFOLib::CFO_Registers::ReadLinkEnabled(const CFO_Link_ID& link, std::optional<uint32_t> val)
     444              : {
     445            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
     446            0 :         return DTC_LinkEnableMode(dataSet[link], dataSet[link + 8]);
     447              : }
     448              : 
     449            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatLinkEnable()
     450              : {
     451            0 :         auto form = CreateFormatter(CFOandDTC_Register_LinkEnable);
     452            0 :         form.description = "Link Enable";
     453            0 :         form.vals.push_back("       ([TX, RX, Timing])");
     454            0 :         for (auto r : CFO_Links)
     455              :         {
     456            0 :                 auto re = ReadLinkEnabled(r);
     457            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.TransmitEnable ? "x" : " ") + "," +
     458            0 :                                                         (re.ReceiveEnable ? "x" : " ") + "]");
     459              :         }
     460            0 :         return form;
     461            0 : }
     462              : 
     463              : // SERDES Reset Register
     464            0 : void CFOLib::CFO_Registers::ResetSERDES(const CFO_Link_ID& link, int interval)
     465              : {
     466            0 :         TLOG(TLVL_SERDESReset) << __COUT_HDR__ << "Entering SERDES Reset Loop for Link " << link;
     467            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
     468            0 :         if (link == CFO_Link_ALL)
     469              :         {
     470            0 :                 for (uint8_t i = 0; i < 8; ++i)
     471            0 :                         data[i] = 1;
     472              :         }
     473              :         else
     474            0 :                 data[link] = 1;
     475            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
     476              : 
     477              :         // usleep(interval);
     478              : 
     479            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
     480            0 :         if (link == CFO_Link_ALL)
     481              :         {
     482            0 :                 for (uint8_t i = 0; i < 8; ++i)
     483            0 :                         data[i] = 0;
     484              :         }
     485              :         else
     486            0 :                 data[link] = 0;
     487            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
     488              : 
     489            0 :         auto resetDone = false;
     490            0 :         uint32_t loops = 0;
     491            0 :         while (!resetDone && ++loops < 100)
     492              :         {
     493            0 :                 usleep(interval);
     494              : 
     495            0 :                 if (link == CFO_Link_ALL)
     496              :                 {
     497            0 :                         uint32_t readData = ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
     498            0 :                         resetDone = ((readData & 0xFF) == 0xFF);
     499              :                 }
     500              :                 else
     501            0 :                         resetDone = ReadResetSERDESDone(link);
     502            0 :                 TLOG(TLVL_SERDESReset) << __COUT_HDR__ << "End of SERDES Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
     503              :         }
     504            0 :         if (loops >= 100)
     505              :         {
     506            0 :                 uint32_t resetDoneReg = ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
     507            0 :                 uint32_t linkEnableReg = ReadRegister_(CFOandDTC_Register_LinkEnable);
     508              :                 // __SS__
     509            0 :                 __COUT_WARN__ << "Timeout waiting for SERDES Reset loop=" << loops
     510            0 :                                           << ". SERDES Reset Done mask=0x" << std::hex << (resetDoneReg & 0xFF)
     511            0 :                                           << ", Link Enable mask=0x" << (linkEnableReg & 0xFF) << std::dec
     512            0 :                                           << ". This may not be an issue if not all CFO 8 links are active.";
     513              :                 // __SS_THROW__;
     514              :         }
     515            0 : }
     516              : 
     517            0 : void CFOLib::CFO_Registers::ResetAllSERDESPlls()
     518              : {
     519            0 :         WriteRegister_(0x0000ff00, CFOandDTC_Register_SERDES_Reset);
     520            0 :         WriteRegister_(0x0, CFOandDTC_Register_SERDES_Reset);
     521            0 :         sleep(3);
     522            0 : }
     523            0 : void CFOLib::CFO_Registers::ResetAllSERDESTx()
     524              : {
     525            0 :         WriteRegister_(0x00ff0000, CFOandDTC_Register_SERDES_Reset);
     526            0 :         WriteRegister_(0x0, CFOandDTC_Register_SERDES_Reset);
     527            0 :         sleep(3);
     528            0 : }
     529              : 
     530            0 : bool CFOLib::CFO_Registers::ReadResetSERDES(const CFO_Link_ID& link, std::optional<uint32_t> val)
     531              : {
     532            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
     533            0 :         return dataSet[link];
     534              : }
     535              : 
     536            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESReset()
     537              : {
     538            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_Reset);
     539            0 :         form.description = "SERDES Reset";
     540            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     541            0 :         for (auto r : CFO_Links)
     542            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
     543            0 :                                                         (ReadResetSERDES(r, form.value) ? "x" : " ") + "]");
     544              : 
     545            0 :         return form;
     546            0 : }
     547              : 
     548              : // SERDES RX Disparity Error Register
     549            0 : DTCLib::DTC_SERDESRXDisparityError CFOLib::CFO_Registers::ReadSERDESRXDisparityError(const CFO_Link_ID& link, std::optional<uint32_t> val)
     550              : {
     551            0 :         return DTC_SERDESRXDisparityError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXDisparityError), static_cast<DTC_Link_ID>(link));
     552              : }
     553              : 
     554            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESRXDisparityError()
     555              : {
     556            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXDisparityError);
     557            0 :         form.description = "SERDES RX Disparity Error";
     558            0 :         form.vals.push_back("       ([H,L])");
     559            0 :         for (auto r : CFO_Links)
     560              :         {
     561            0 :                 auto re = ReadSERDESRXDisparityError(r, form.value);
     562            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + std::to_string(re.GetData()[1]) + "," +
     563            0 :                                                         std::to_string(re.GetData()[0]) + "]");
     564              :         }
     565            0 :         return form;
     566            0 : }
     567              : 
     568              : // SERDES RX Character Not In Table Error Register
     569            0 : DTCLib::DTC_CharacterNotInTableError CFOLib::CFO_Registers::ReadSERDESRXCharacterNotInTableError(const CFO_Link_ID& link, std::optional<uint32_t> val)
     570              : {
     571            0 :         return DTC_CharacterNotInTableError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXCharacterNotInTableError),
     572            0 :                                                                                 static_cast<DTC_Link_ID>(link));
     573              : }
     574              : 
     575            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESRXCharacterNotInTableError()
     576              : {
     577            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXCharacterNotInTableError);
     578            0 :         form.description = "SERDES RX CNIT Error";
     579            0 :         form.vals.push_back("       ([H,L])");
     580            0 :         for (auto r : CFO_Links)
     581              :         {
     582            0 :                 auto re = ReadSERDESRXCharacterNotInTableError(r, form.value);
     583            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + std::to_string(re.GetData()[1]) + "," +
     584            0 :                                                         std::to_string(re.GetData()[0]) + "]");
     585              :         }
     586            0 :         return form;
     587            0 : }
     588              : 
     589              : // SERDES Unlock Error Register
     590            0 : bool CFOLib::CFO_Registers::ReadSERDESUnlockError(const CFO_Link_ID& link, std::optional<uint32_t> val)
     591              : {
     592            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
     593            0 :         return dataSet[link];
     594              : }
     595              : 
     596            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESUnlockError()
     597              : {
     598            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_UnlockError);
     599            0 :         form.description = "SERDES Unlock Error";
     600            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     601            0 :         for (auto r : CFO_Links)
     602            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
     603            0 :                                                         (ReadSERDESUnlockError(r, form.value) ? "x" : " ") +
     604              :                                                         "]");
     605            0 :         return form;
     606            0 : }
     607              : 
     608              : // SERDES PLL Locked Register
     609            0 : bool CFOLib::CFO_Registers::ReadSERDESPLLLocked(const CFO_Link_ID& link, std::optional<uint32_t> val)
     610              : {
     611            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLLocked);
     612            0 :         return dataSet[link];
     613              : }
     614              : 
     615            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPLLLocked()
     616              : {
     617            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLLocked);
     618            0 :         form.description = "SERDES PLL Locked";
     619            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     620            0 :         for (auto r : CFO_Links)
     621            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (ReadSERDESPLLLocked(r, form.value) ? "x" : " ") + "]");
     622            0 :         form.vals.push_back(std::string("Clock to JA:    [") + ((((form.value) >> 8) & 1) ? "x" : " ") + "]");
     623            0 :         form.vals.push_back(std::string("Clock from JA:  [") + ((((form.value) >> 9) & 1) ? "x" : " ") + "]");
     624            0 :         return form;
     625            0 : }
     626              : 
     627              : // SERDES RX Status Register
     628            0 : DTCLib::DTC_RXStatus CFOLib::CFO_Registers::ReadSERDESRXStatus(const CFO_Link_ID& link, std::optional<uint32_t> val)
     629              : {
     630            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXStatus);
     631            0 :         data = (data >> (3 * link)) & 0x7;
     632            0 :         return static_cast<DTC_RXStatus>(data);
     633              : }
     634              : 
     635            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESRXStatus()
     636              : {
     637            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXStatus);
     638            0 :         form.description = "SERDES RX Status";
     639            0 :         form.vals.push_back("");  // translation
     640            0 :         for (auto r : CFO_Links)
     641              :         {
     642            0 :                 auto re = ReadSERDESRXStatus(r, form.value);
     643            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " + DTC_RXStatusConverter(re).toString());
     644              :         }
     645              : 
     646            0 :         return form;
     647            0 : }
     648              : 
     649              : // SERDES Reset Done Register
     650            0 : bool CFOLib::CFO_Registers::ReadResetSERDESDone(const CFO_Link_ID& link, std::optional<uint32_t> val)
     651              : {
     652            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
     653            0 :         return dataSet[link];
     654              : }
     655              : 
     656            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESResetDone()
     657              : {
     658            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_ResetDone);
     659            0 :         form.description = "SERDES Reset Done";
     660            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     661            0 :         for (auto r : CFO_Links)
     662            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
     663            0 :                                                         (ReadResetSERDESDone(r, form.value) ? "x" : " ") + "]");
     664            0 :         return form;
     665            0 : }
     666              : 
     667              : // SFP / SERDES Status Register
     668              : 
     669            0 : bool CFOLib::CFO_Registers::ReadSERDESRXCDRLock(const CFO_Link_ID& link, std::optional<uint32_t> val)
     670              : {
     671            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_SFPSERDESStatus);
     672            0 :         return dataSet[link];
     673              : }
     674              : 
     675            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESRXCDRLock()
     676              : {
     677            0 :         auto form = CreateFormatter(CFO_Register_SFPSERDESStatus);
     678            0 :         form.description = "SERDES CDR Lock";
     679            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     680            0 :         for (auto r : CFO_Links)
     681            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
     682            0 :                                                         (ReadSERDESRXCDRLock(r, form.value) ? "x" : " ") + "]");
     683            0 :         return form;
     684            0 : }
     685              : 
     686            0 : void CFOLib::CFO_Registers::SetBeamOnTimerPreset(uint32_t preset)
     687              : {
     688            0 :         WriteRegister_(preset, CFO_Register_BeamOnTimerPreset);
     689            0 : }
     690              : 
     691            0 : uint32_t CFOLib::CFO_Registers::ReadBeamOnTimerPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(CFO_Register_BeamOnTimerPreset); }
     692              : 
     693            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatBeamOnTimerPreset()
     694              : {
     695            0 :         auto form = CreateFormatter(CFO_Register_BeamOnTimerPreset);
     696            0 :         form.description = "Beam On Timer Preset Register";
     697            0 :         form.vals.push_back(std::to_string(ReadBeamOnTimerPreset(form.value)));
     698            0 :         return form;
     699            0 : }
     700              : 
     701            0 : void CFOLib::CFO_Registers::EnableBeamOnMode(const CFO_Link_ID& link)
     702              : {
     703            0 :         SetLinuxTimestampPreset();
     704            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_EnableBeamOnMode);
     705            0 :         data[0] = 1;  // Enable beam on processing a single global flag as of December 2023
     706            0 :         WriteRegister_(data.to_ulong(), CFO_Register_EnableBeamOnMode);
     707            0 : }
     708              : 
     709            0 : void CFOLib::CFO_Registers::DisableBeamOnMode(const CFO_Link_ID& link)
     710              : {
     711            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_EnableBeamOnMode);
     712            0 :         data[0] = 0;  // Enable beam on processing a single global flag as of December 2023
     713            0 :         WriteRegister_(data.to_ulong(), CFO_Register_EnableBeamOnMode);
     714            0 : }
     715              : 
     716            0 : bool CFOLib::CFO_Registers::ReadBeamOnMode(std::optional<uint32_t> val)
     717              : {
     718            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_EnableBeamOnMode);
     719            0 :         return data[0];  // Enable beam on processing a single global flag as of December 2023
     720              : }
     721              : 
     722            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatBeamOnMode()
     723              : {
     724            0 :         auto form = CreateFormatter(CFO_Register_EnableBeamOnMode);
     725            0 :         form.description = "Enable Beam On Mode Register";
     726            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     727              :                                                                                         // Enable beam on processing a single global flag as of December 2023
     728            0 :         form.vals.push_back(std::string("Beam On Processing ") + ": [" + (ReadBeamOnMode(form.value) ? "x" : " ") + "]");
     729            0 :         return form;
     730            0 : }
     731              : 
     732            0 : void CFOLib::CFO_Registers::EnableBeamOffMode(const CFO_Link_ID& link)
     733              : {
     734            0 :         SetLinuxTimestampPreset();
     735            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_EnableBeamOffMode);
     736            0 :         data[0] = 1;  // Enable beam off processing a single global flag as of December 2023
     737            0 :         WriteRegister_(data.to_ulong(), CFO_Register_EnableBeamOffMode);
     738            0 : }
     739              : 
     740            0 : void CFOLib::CFO_Registers::DisableBeamOffMode(const CFO_Link_ID& link)
     741              : {
     742            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_EnableBeamOffMode);
     743            0 :         data[0] = 0;  // Enable off processing a single global flag as of December 2023
     744            0 :         WriteRegister_(data.to_ulong(), CFO_Register_EnableBeamOffMode);
     745            0 : }
     746              : 
     747            0 : bool CFOLib::CFO_Registers::ReadBeamOffMode(std::optional<uint32_t> val)
     748              : {
     749            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_EnableBeamOffMode);
     750            0 :         return data[0];  // Enable beam on processing a single global flag as of December 2023
     751              : }
     752              : 
     753            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatBeamOffMode()
     754              : {
     755            0 :         auto form = CreateFormatter(CFO_Register_EnableBeamOffMode);
     756            0 :         form.description = "Enable Beam Off Mode Register";
     757            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     758              :         // Enable off processing a single global flag as of December 2023
     759            0 :         form.vals.push_back(std::string("Beam Off Processing ") + ": [" + (ReadBeamOffMode(form.value) ? "x" : " ") + "]");
     760            0 :         return form;
     761            0 : }
     762              : 
     763              : // LEGACY: register 0x9154 repurposed as RunPlanSubrunEvtLimit; these functions are no longer valid
     764              : // void CFOLib::CFO_Registers::SetClockMarkerIntervalCount(uint32_t data)
     765              : // {
     766              : //      WriteRegister_(data, CFO_Register_ClockMarkerIntervalCount);
     767              : // }
     768              : 
     769              : // LEGACY: register 0x9154 repurposed as RunPlanSubrunEvtLimit; these functions are no longer valid
     770              : // uint32_t CFOLib::CFO_Registers::ReadClockMarkerIntervalCount(std::optional<uint32_t> val)
     771              : // {
     772              : //      return val.has_value() ? *val : ReadRegister_(CFO_Register_ClockMarkerIntervalCount);
     773              : // }
     774              : 
     775              : // LEGACY: register 0x9154 repurposed as RunPlanSubrunEvtLimit; these functions are no longer valid
     776              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatClockMarkerIntervalCount()
     777              : // {
     778              : //      auto form = CreateFormatter(CFO_Register_ClockMarkerIntervalCount);
     779              : //      form.description = "40 MHz Clock Marker Interval Count Register";
     780              : //      form.vals.push_back(std::to_string(ReadClockMarkerIntervalCount()));
     781              : //      return form;
     782              : // }
     783              : 
     784              : // SEREDES Oscillator Registers
     785            0 : uint32_t CFOLib::CFO_Registers::ReadSERDESOscillatorFrequency(std::optional<uint32_t> val)
     786              : {
     787            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_SERDESOscillatorFrequency);
     788              : }
     789            0 : void CFOLib::CFO_Registers::SetSERDESOscillatorFrequency(uint32_t freq)
     790              : {
     791            0 :         WriteRegister_(freq, CFO_Register_SERDESOscillatorFrequency);
     792            0 : }
     793            0 : bool CFOLib::CFO_Registers::ReadSERDESOscillatorIICInterfaceReset(std::optional<uint32_t> val)
     794              : {
     795            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFO_Register_SERDESClock_IICBusControl));
     796            0 :         return dataSet[31];
     797              : }
     798              : 
     799            0 : void CFOLib::CFO_Registers::ResetSERDESOscillatorIICInterface()
     800              : {
     801            0 :         auto bs = std::bitset<32>();
     802            0 :         bs[31] = 1;
     803            0 :         WriteRegister_(bs.to_ulong(), CFO_Register_SERDESClock_IICBusControl);
     804            0 :         while (ReadSERDESOscillatorIICInterfaceReset())
     805              :         {
     806            0 :                 usleep(1000);
     807              :         }
     808            0 : }
     809              : 
     810              : // Jitter Attenuator CSR Register
     811              : /// <summary>
     812              : /// Read the value of the Jitter Attenuator Select
     813              : /// </summary>
     814              : /// <returns>Jitter Attenuator Select value</returns>
     815            0 : std::bitset<2> CFOLib::CFO_Registers::ReadJitterAttenuatorSelect(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorSelect(CFO_Register_JitterAttenuatorCSR, val); }
     816              : 
     817              : /// <summary>
     818              : /// Set the Jitter Attenuator Select bits
     819              : /// </summary>
     820              : /// <param name="data">Value to set</param>
     821            0 : void CFOLib::CFO_Registers::SetJitterAttenuatorSelect(std::bitset<2> data, bool alsoResetJA /* = false */) { CFOandDTC_Registers::SetJitterAttenuatorSelect(CFO_Register_JitterAttenuatorCSR, data, alsoResetJA); }
     822              : 
     823              : /// <summary>
     824              : /// Read the Jitter Attenuator Reset bit
     825              : /// </summary>
     826              : /// <returns>Value of the Jitter Attenuator Reset bit</returns>
     827            0 : bool CFOLib::CFO_Registers::ReadJitterAttenuatorReset(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorReset(CFO_Register_JitterAttenuatorCSR, val); }
     828            0 : bool CFOLib::CFO_Registers::ReadJitterAttenuatorLocked(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorLocked(CFO_Register_JitterAttenuatorCSR, val); }
     829              : 
     830              : /// <summary>
     831              : /// Reset the Jitter Attenuator
     832              : /// </summary>
     833            0 : void CFOLib::CFO_Registers::ResetJitterAttenuator() { CFOandDTC_Registers::ResetJitterAttenuator(CFO_Register_JitterAttenuatorCSR); }
     834              : 
     835              : /// <summary>
     836              : /// Formats the register's current value for register dumps
     837              : /// </summary>
     838              : /// <returns>RegisterFormatter object containing register information</returns>
     839            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatJitterAttenuatorCSR() { return CFOandDTC_Registers::FormatJitterAttenuatorCSR(CFO_Register_JitterAttenuatorCSR); }
     840              : 
     841            0 : uint64_t CFOLib::CFO_Registers::ReadSERDESOscillatorParameters(std::optional<uint32_t> val)
     842              : {
     843            0 :         uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7)) << 40) +
     844            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8)) << 32) +
     845            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9)) << 24) +
     846            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10)) << 16) +
     847            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11)) << 8) +
     848            0 :                                         static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12));
     849            0 :         return data;
     850              : }
     851            0 : void CFOLib::CFO_Registers::SetSERDESOscillatorParameters(uint64_t program)
     852              : {
     853            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0x10);
     854              : 
     855            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7, static_cast<uint8_t>(program >> 40));
     856            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8, static_cast<uint8_t>(program >> 32));
     857            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9, static_cast<uint8_t>(program >> 24));
     858            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10, static_cast<uint8_t>(program >> 16));
     859            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11, static_cast<uint8_t>(program >> 8));
     860            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12, static_cast<uint8_t>(program));
     861              : 
     862            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0);
     863            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x87, 0x40);
     864            0 : }
     865              : 
     866            0 : DTCLib::DTC_SerdesClockSpeed CFOLib::CFO_Registers::ReadSERDESOscillatorClock(std::optional<uint32_t> val)
     867              : {
     868            0 :         auto freq = ReadSERDESOscillatorFrequency(val);
     869              : 
     870              :         // Clocks should be accurate to 30 ppm
     871            0 :         if (freq > 156250000 - 4687.5 && freq < 156250000 + 4687.5) return DTC_SerdesClockSpeed_3125Gbps;
     872            0 :         if (freq > 125000000 - 3750 && freq < 125000000 + 3750) return DTC_SerdesClockSpeed_25Gbps;
     873            0 :         return DTC_SerdesClockSpeed_Unknown;
     874              : }
     875            0 : void CFOLib::CFO_Registers::SetSERDESOscillatorClock(DTC_SerdesClockSpeed speed)
     876              : {
     877              :         double targetFreq;
     878            0 :         switch (speed)
     879              :         {
     880            0 :                 case DTC_SerdesClockSpeed_25Gbps:
     881            0 :                         targetFreq = 125000000.0;
     882            0 :                         break;
     883            0 :                 case DTC_SerdesClockSpeed_3125Gbps:
     884            0 :                         targetFreq = 156250000.0;
     885            0 :                         break;
     886            0 :                 case DTC_SerdesClockSpeed_48Gbps:
     887            0 :                         targetFreq = 240000000.0;
     888            0 :                         break;
     889            0 :                 default:
     890            0 :                         targetFreq = 0.0;
     891            0 :                         break;
     892              :         }
     893            0 :         if (SetNewOscillatorFrequency(targetFreq))
     894              :         {
     895            0 :                 for (auto& Link : CFO_Links)
     896              :                 {
     897            0 :                         ResetSERDES(Link, 1000);
     898              :                 }
     899              :         }
     900            0 : }
     901              : 
     902            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESOscillatorFrequency()
     903              : {
     904            0 :         auto form = CreateFormatter(CFO_Register_SERDESOscillatorFrequency);
     905            0 :         form.description = "SERDES Oscillator Frequency";
     906            0 :         std::stringstream o;
     907            0 :         o << std::dec << ReadSERDESOscillatorFrequency(form.value);
     908            0 :         form.vals.push_back(o.str());
     909            0 :         return form;
     910            0 : }
     911            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESOscillatorControl()
     912              : {
     913            0 :         auto form = CreateFormatter(CFO_Register_SERDESClock_IICBusControl);
     914            0 :         form.description = "SERDES Oscillator IIC Bus Control";
     915            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     916            0 :         form.vals.push_back(std::string("Reset:  [") + (ReadSERDESOscillatorIICInterfaceReset() ? "x" : " ") + "]");
     917            0 :         return form;
     918            0 : }
     919              : 
     920              : /// Timestamp Preset Registers
     921            0 : void CFOLib::CFO_Registers::SetEventWindowTagPreset(const DTC_EventWindowTag& preset)
     922              : {
     923            0 :         auto timestamp = preset.GetEventWindowTag();
     924            0 :         auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
     925            0 :         timestamp >>= 32;
     926            0 :         auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
     927              : 
     928            0 :         WriteRegister_(timestampLow, CFO_Register_TimestampPreset0);
     929            0 :         WriteRegister_(timestampHigh, CFO_Register_TimestampPreset1);
     930            0 : }
     931              : 
     932            0 : DTCLib::DTC_EventWindowTag CFOLib::CFO_Registers::ReadTimestampPreset(std::optional<uint32_t> val)
     933              : {
     934            0 :         auto timestampLow = val.has_value() ? *val : ReadRegister_(CFO_Register_TimestampPreset0);
     935            0 :         DTC_EventWindowTag output;
     936            0 :         output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(CFO_Register_TimestampPreset1)));
     937            0 :         return output;
     938            0 : }
     939              : 
     940            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTimestampPreset0()
     941              : {
     942            0 :         auto form = CreateFormatter(CFO_Register_TimestampPreset0);
     943            0 :         form.description = "Timestamp Preset 0";
     944            0 :         std::stringstream o;
     945            0 :         o << "0x" << std::hex << ReadRegister_(CFO_Register_TimestampPreset0);
     946            0 :         form.vals.push_back(o.str());
     947            0 :         return form;
     948            0 : }
     949              : 
     950            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTimestampPreset1()
     951              : {
     952            0 :         auto form = CreateFormatter(CFO_Register_TimestampPreset1);
     953            0 :         form.description = "Timestamp Preset 1";
     954            0 :         std::stringstream o;
     955            0 :         o << "0x" << std::hex << ReadRegister_(CFO_Register_TimestampPreset1);
     956            0 :         form.vals.push_back(o.str());
     957            0 :         return form;
     958            0 : }
     959              : 
     960              : /// Linux Timestamp Register
     961            0 : void CFOLib::CFO_Registers::SetLinuxTimestampPreset()
     962              : {
     963            0 :         WriteRegister_(time(0), CFO_Register_LinuxTimestamp);
     964            0 : }
     965              : 
     966            0 : time_t CFOLib::CFO_Registers::ReadLinuxTimestamp()
     967              : {
     968            0 :         auto val = ReadRegister_(CFO_Register_LinuxTimestamp);
     969            0 :         return val;
     970              : }
     971              : 
     972              : // FIFO Full Error Flags Registers
     973            0 : void CFOLib::CFO_Registers::ClearFIFOFullErrorFlags(const CFO_Link_ID& link)
     974              : {
     975            0 :         auto flags = ReadFIFOFullErrorFlags(link);
     976            0 :         std::bitset<32> data0 = 0;
     977              : 
     978            0 :         data0[link] = flags.CFOLinkInput;
     979              : 
     980            0 :         WriteRegister_(data0.to_ulong(), CFO_Register_FIFOFullErrorFlag0);
     981            0 : }
     982              : 
     983            0 : DTCLib::DTC_FIFOFullErrorFlags CFOLib::CFO_Registers::ReadFIFOFullErrorFlags(const CFO_Link_ID& link, std::optional<uint32_t> val)
     984              : {
     985            0 :         std::bitset<32> data0 = val.has_value() ? *val : ReadRegister_(CFO_Register_FIFOFullErrorFlag0);
     986            0 :         DTC_FIFOFullErrorFlags flags;
     987              : 
     988            0 :         flags.CFOLinkInput = data0[link];
     989              : 
     990            0 :         return flags;
     991              : }
     992              : 
     993            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatFIFOFullErrorFlag0()
     994              : {
     995            0 :         auto form = CreateFormatter(CFO_Register_FIFOFullErrorFlag0);
     996            0 :         form.description = "FIFO Full Error Flags 0";
     997            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
     998            0 :         for (auto r : CFO_Links)
     999              :         {
    1000            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    1001            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.CFOLinkInput ? "x" : " ") + "]");
    1002              :         }
    1003            0 :         return form;
    1004            0 : }
    1005              : 
    1006              : // Receive Packet Error Register
    1007            0 : void CFOLib::CFO_Registers::ClearRXElasticBufferUnderrun(const CFO_Link_ID& link)
    1008              : {
    1009            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_ReceivePacketError);
    1010            0 :         data[static_cast<int>(link) + 24] = 0;
    1011            0 :         WriteRegister_(data.to_ulong(), CFO_Register_ReceivePacketError);
    1012            0 : }
    1013              : 
    1014            0 : bool CFOLib::CFO_Registers::ReadRXElasticBufferUnderrun(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1015              : {
    1016            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_ReceivePacketError);
    1017            0 :         return data[static_cast<int>(link) + 24];
    1018              : }
    1019              : 
    1020            0 : void CFOLib::CFO_Registers::ClearRXElasticBufferOverrun(const CFO_Link_ID& link)
    1021              : {
    1022            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_ReceivePacketError);
    1023            0 :         data[static_cast<int>(link) + 16] = 0;
    1024            0 :         WriteRegister_(data.to_ulong(), CFO_Register_ReceivePacketError);
    1025            0 : }
    1026              : 
    1027            0 : bool CFOLib::CFO_Registers::ReadRXElasticBufferOverrun(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1028              : {
    1029            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_ReceivePacketError);
    1030            0 :         return data[static_cast<int>(link) + 16];
    1031              : }
    1032              : 
    1033            0 : void CFOLib::CFO_Registers::ClearPacketError(const CFO_Link_ID& link)
    1034              : {
    1035            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_ReceivePacketError);
    1036            0 :         data[static_cast<int>(link) + 8] = 0;
    1037            0 :         WriteRegister_(data.to_ulong(), CFO_Register_ReceivePacketError);
    1038            0 : }
    1039              : 
    1040            0 : bool CFOLib::CFO_Registers::ReadPacketError(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1041              : {
    1042            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_ReceivePacketError);
    1043            0 :         return data[static_cast<int>(link) + 8];
    1044              : }
    1045              : 
    1046            0 : void CFOLib::CFO_Registers::ClearPacketCRCError(const CFO_Link_ID& link)
    1047              : {
    1048            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_ReceivePacketError);
    1049            0 :         data[static_cast<int>(link)] = 0;
    1050            0 :         WriteRegister_(data.to_ulong(), CFO_Register_ReceivePacketError);
    1051            0 : }
    1052              : 
    1053            0 : bool CFOLib::CFO_Registers::ReadPacketCRCError(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1054              : {
    1055            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_ReceivePacketError);
    1056            0 :         return data[static_cast<int>(link)];
    1057              : }
    1058              : 
    1059            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketError()
    1060              : {
    1061            0 :         auto form = CreateFormatter(CFO_Register_ReceivePacketError);
    1062            0 :         form.description = "Receive Packet Error";
    1063            0 :         form.vals.push_back("       ([CRC, PacketError, RX Overrun, RX Underrun])");
    1064            0 :         for (auto r : CFO_Links)
    1065            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    1066            0 :                                                         (ReadPacketCRCError(r, form.value) ? "x" : " ") + "," +
    1067            0 :                                                         (ReadPacketError(r, form.value) ? "x" : " ") + "," +
    1068            0 :                                                         (ReadRXElasticBufferOverrun(r, form.value) ? "x" : " ") + "," +
    1069            0 :                                                         (ReadRXElasticBufferUnderrun(r, form.value) ? "x" : " ") + "]");
    1070            0 :         return form;
    1071            0 : }
    1072              : 
    1073            0 : void CFOLib::CFO_Registers::SetEventWindowEmulatorInterval(const uint32_t& data)
    1074              : {
    1075            0 :         __SS__ << "Access attempt of CFO_Register_EventWindowEmulatorIntervalTime = 0x91A0,.."
    1076              :                           "this register was deleted in Firmware version: Nov/09/2023 11:00   raw-data: 0x23110911; "
    1077            0 :                           "please update the software to use the CFO Run Plan to control the Event Window duration."
    1078            0 :                    << __E__;
    1079            0 :         __SS_THROW__;
    1080              :         // WriteRegister_(data, CFO_Register_EventWindowEmulatorIntervalTime);
    1081            0 : }
    1082              : 
    1083            0 : uint32_t CFOLib::CFO_Registers::ReadEventWindowEmulatorInterval(std::optional<uint32_t> val)
    1084              : {
    1085            0 :         __SS__ << "Access attempt of CFO_Register_EventWindowEmulatorIntervalTime = 0x91A0,.."
    1086              :                           "this register was deleted in Firmware version: Nov/09/2023 11:00   raw-data: 0x23110911; "
    1087            0 :                           "please update the software to use the CFO Run Plan to control the Event Window duration."
    1088            0 :                    << __E__;
    1089            0 :         __SS_THROW__;
    1090              :         // return val.has_value()?*val:ReadRegister_(CFO_Register_EventWindowEmulatorIntervalTime);
    1091            0 : }
    1092              : 
    1093            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatEventWindowEmulatorIntervalTime()
    1094              : {
    1095            0 :         __SS__ << "Access attempt of CFO_Register_EventWindowEmulatorIntervalTime = 0x91A0,.."
    1096              :                           "this register was deleted in Firmware version: Nov/09/2023 11:00   raw-data: 0x23110911; "
    1097            0 :                           "please update the software to use the CFO Run Plan to control the Event Window duration."
    1098            0 :                    << __E__;
    1099            0 :         __SS_THROW__;
    1100              :         // auto form = CreateFormatter(CFO_Register_EventWindowEmulatorIntervalTime);
    1101              :         // form.description = "Event Window Emulator Interval Time";
    1102              :         // form.vals.push_back(std::to_string(ReadEventWindowEmulatorInterval()));
    1103              :         // return form;
    1104            0 : }
    1105              : 
    1106            0 : void CFOLib::CFO_Registers::SetEventWindowHoldoffTime(const uint32_t& data)
    1107              : {
    1108            0 :         WriteRegister_(data, CFO_Register_EventWindowHoldoffTime);
    1109            0 : }
    1110              : 
    1111            0 : uint32_t CFOLib::CFO_Registers::ReadEventWindowHoldoffTime(std::optional<uint32_t> val)
    1112              : {
    1113            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_EventWindowHoldoffTime);
    1114              : }
    1115              : 
    1116            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatEventWindowHoldoffTime()
    1117              : {
    1118            0 :         auto form = CreateFormatter(CFO_Register_EventWindowHoldoffTime);
    1119            0 :         form.description = "Event Window Holdoff Time";
    1120            0 :         form.vals.push_back(std::to_string(ReadEventWindowHoldoffTime(form.value)));
    1121            0 :         return form;
    1122            0 : }
    1123              : 
    1124            0 : bool CFOLib::CFO_Registers::ReadEventWindowTimeoutError(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1125              : {
    1126            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_EventWindowTimeoutError);
    1127            0 :         return dataSet[link];
    1128              : }
    1129              : 
    1130            0 : void CFOLib::CFO_Registers::ClearEventWindowTimeoutError(const CFO_Link_ID& link)
    1131              : {
    1132            0 :         std::bitset<32> data = ReadRegister_(CFO_Register_EventWindowTimeoutError);
    1133            0 :         data[link] = 1;
    1134            0 :         WriteRegister_(data.to_ulong(), CFO_Register_EventWindowTimeoutError);
    1135            0 : }
    1136              : 
    1137            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatEventWindowTimeoutError()
    1138              : {
    1139            0 :         auto form = CreateFormatter(CFO_Register_EventWindowTimeoutError);
    1140            0 :         form.description = "Event Window Timeout Error";
    1141            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
    1142            0 :         for (auto r : CFO_Links)
    1143            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    1144            0 :                                                         (ReadEventWindowTimeoutError(r, form.value) ? "x" : " ") + "]");
    1145            0 :         return form;
    1146            0 : }
    1147              : 
    1148            0 : void CFOLib::CFO_Registers::SetEventWindowTimeoutInterval(const uint32_t& data)
    1149              : {
    1150            0 :         WriteRegister_(data, CFO_Register_EventWindowTimeoutValue);
    1151            0 : }
    1152              : 
    1153            0 : uint32_t CFOLib::CFO_Registers::ReadEventWindowTimeoutInterval(std::optional<uint32_t> val)
    1154              : {
    1155            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_EventWindowTimeoutValue);
    1156              : }
    1157              : 
    1158            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatEventWindowTimeoutInterval()
    1159              : {
    1160            0 :         auto form = CreateFormatter(CFO_Register_EventWindowTimeoutValue);
    1161            0 :         form.description = "Event Window Timeout Value";
    1162            0 :         form.vals.push_back(std::to_string(ReadEventWindowTimeoutInterval()));
    1163            0 :         return form;
    1164            0 : }
    1165              : 
    1166              : // // SERDES Counter Registers
    1167              : // void CFOLib::CFO_Registers::ClearReceiveByteCount(const CFO_Link_ID& link)
    1168              : // {
    1169              : //      CFO_Register reg;
    1170              : //      switch (link)
    1171              : //      {
    1172              : //              case CFO_Link_0:
    1173              : //                      reg = CFO_Register_ReceiveByteCountDataLink0;
    1174              : //                      break;
    1175              : //              case CFO_Link_1:
    1176              : //                      reg = CFO_Register_ReceiveByteCountDataLink1;
    1177              : //                      break;
    1178              : //              case CFO_Link_2:
    1179              : //                      reg = CFO_Register_ReceiveByteCountDataLink2;
    1180              : //                      break;
    1181              : //              case CFO_Link_3:
    1182              : //                      reg = CFO_Register_ReceiveByteCountDataLink3;
    1183              : //                      break;
    1184              : //              case CFO_Link_4:
    1185              : //                      reg = CFO_Register_ReceiveByteCountDataLink4;
    1186              : //                      break;
    1187              : //              case CFO_Link_5:
    1188              : //                      reg = CFO_Register_ReceiveByteCountDataLink5;
    1189              : //                      break;
    1190              : //              case CFO_Link_6:
    1191              : //                      reg = CFO_Register_ReceiveByteCountDataLink6;
    1192              : //                      break;
    1193              : //              case CFO_Link_7:
    1194              : //                      reg = CFO_Register_ReceiveByteCountDataLink7;
    1195              : //                      break;
    1196              : //              default: {
    1197              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1198              : //                      __SS_THROW__;
    1199              : //              }
    1200              : //      }
    1201              : //      WriteRegister_(0, reg);
    1202              : // }
    1203              : 
    1204              : // uint32_t CFOLib::CFO_Registers::ReadReceiveByteCount(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1205              : // {
    1206              : //      CFO_Register reg;
    1207              : //      switch (link)
    1208              : //      {
    1209              : //              case CFO_Link_0:
    1210              : //                      reg = CFO_Register_ReceiveByteCountDataLink0;
    1211              : //                      break;
    1212              : //              case CFO_Link_1:
    1213              : //                      reg = CFO_Register_ReceiveByteCountDataLink1;
    1214              : //                      break;
    1215              : //              case CFO_Link_2:
    1216              : //                      reg = CFO_Register_ReceiveByteCountDataLink2;
    1217              : //                      break;
    1218              : //              case CFO_Link_3:
    1219              : //                      reg = CFO_Register_ReceiveByteCountDataLink3;
    1220              : //                      break;
    1221              : //              case CFO_Link_4:
    1222              : //                      reg = CFO_Register_ReceiveByteCountDataLink4;
    1223              : //                      break;
    1224              : //              case CFO_Link_5:
    1225              : //                      reg = CFO_Register_ReceiveByteCountDataLink5;
    1226              : //                      break;
    1227              : //              case CFO_Link_6:
    1228              : //                      reg = CFO_Register_ReceiveByteCountDataLink6;
    1229              : //                      break;
    1230              : //              case CFO_Link_7:
    1231              : //                      reg = CFO_Register_ReceiveByteCountDataLink7;
    1232              : //                      break;
    1233              : //              default: {
    1234              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1235              : //                      __SS_THROW__;
    1236              : //              }
    1237              : //      }
    1238              : //      return val.has_value() ? *val : ReadRegister_(reg);
    1239              : // }
    1240              : 
    1241              : // void CFOLib::CFO_Registers::ClearReceivePacketCount(const CFO_Link_ID& link)
    1242              : // {
    1243              : //      CFO_Register reg;
    1244              : //      switch (link)
    1245              : //      {
    1246              : //              case CFO_Link_0:
    1247              : //                      reg = CFO_Register_ReceivePacketCountDataLink0;
    1248              : //                      break;
    1249              : //              case CFO_Link_1:
    1250              : //                      reg = CFO_Register_ReceivePacketCountDataLink1;
    1251              : //                      break;
    1252              : //              case CFO_Link_2:
    1253              : //                      reg = CFO_Register_ReceivePacketCountDataLink2;
    1254              : //                      break;
    1255              : //              case CFO_Link_3:
    1256              : //                      reg = CFO_Register_ReceivePacketCountDataLink3;
    1257              : //                      break;
    1258              : //              case CFO_Link_4:
    1259              : //                      reg = CFO_Register_ReceivePacketCountDataLink4;
    1260              : //                      break;
    1261              : //              case CFO_Link_5:
    1262              : //                      reg = CFO_Register_ReceivePacketCountDataLink5;
    1263              : //                      break;
    1264              : //              case CFO_Link_6:
    1265              : //                      reg = CFO_Register_ReceivePacketCountDataLink6;
    1266              : //                      break;
    1267              : //              case CFO_Link_7:
    1268              : //                      reg = CFO_Register_ReceivePacketCountDataLink7;
    1269              : //                      break;
    1270              : //              default: {
    1271              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1272              : //                      __SS_THROW__;
    1273              : //              }
    1274              : //      }
    1275              : //      WriteRegister_(0, reg);
    1276              : // }
    1277              : 
    1278              : // uint32_t CFOLib::CFO_Registers::ReadReceivePacketCount(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1279              : // {
    1280              : //      CFO_Register reg;
    1281              : //      switch (link)
    1282              : //      {
    1283              : //              case CFO_Link_0:
    1284              : //                      reg = CFO_Register_ReceivePacketCountDataLink0;
    1285              : //                      break;
    1286              : //              case CFO_Link_1:
    1287              : //                      reg = CFO_Register_ReceivePacketCountDataLink1;
    1288              : //                      break;
    1289              : //              case CFO_Link_2:
    1290              : //                      reg = CFO_Register_ReceivePacketCountDataLink2;
    1291              : //                      break;
    1292              : //              case CFO_Link_3:
    1293              : //                      reg = CFO_Register_ReceivePacketCountDataLink3;
    1294              : //                      break;
    1295              : //              case CFO_Link_4:
    1296              : //                      reg = CFO_Register_ReceivePacketCountDataLink4;
    1297              : //                      break;
    1298              : //              case CFO_Link_5:
    1299              : //                      reg = CFO_Register_ReceivePacketCountDataLink5;
    1300              : //                      break;
    1301              : //              case CFO_Link_6:
    1302              : //                      reg = CFO_Register_ReceivePacketCountDataLink6;
    1303              : //                      break;
    1304              : //              case CFO_Link_7:
    1305              : //                      reg = CFO_Register_ReceivePacketCountDataLink7;
    1306              : //                      break;
    1307              : //              default: {
    1308              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1309              : //                      __SS_THROW__;
    1310              : //              }
    1311              : //      }
    1312              : //      return val.has_value() ? *val : ReadRegister_(reg);
    1313              : // }
    1314              : 
    1315              : // void CFOLib::CFO_Registers::ClearTransmitByteCount(const CFO_Link_ID& link)
    1316              : // {
    1317              : //      CFO_Register reg;
    1318              : //      switch (link)
    1319              : //      {
    1320              : //              case CFO_Link_0:
    1321              : //                      reg = CFO_Register_TransmitByteCountDataLink0;
    1322              : //                      break;
    1323              : //              case CFO_Link_1:
    1324              : //                      reg = CFO_Register_TransmitByteCountDataLink1;
    1325              : //                      break;
    1326              : //              case CFO_Link_2:
    1327              : //                      reg = CFO_Register_TransmitByteCountDataLink2;
    1328              : //                      break;
    1329              : //              case CFO_Link_3:
    1330              : //                      reg = CFO_Register_TransmitByteCountDataLink3;
    1331              : //                      break;
    1332              : //              case CFO_Link_4:
    1333              : //                      reg = CFO_Register_TransmitByteCountDataLink4;
    1334              : //                      break;
    1335              : //              case CFO_Link_5:
    1336              : //                      reg = CFO_Register_TransmitByteCountDataLink5;
    1337              : //                      break;
    1338              : //              case CFO_Link_6:
    1339              : //                      reg = CFO_Register_TransmitByteCountDataLink6;
    1340              : //                      break;
    1341              : //              case CFO_Link_7:
    1342              : //                      reg = CFO_Register_TransmitByteCountDataLink7;
    1343              : //                      break;
    1344              : //              default: {
    1345              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1346              : //                      __SS_THROW__;
    1347              : //              }
    1348              : //      }
    1349              : //      WriteRegister_(0, reg);
    1350              : // }
    1351              : 
    1352              : // uint32_t CFOLib::CFO_Registers::ReadTransmitByteCount(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1353              : // {
    1354              : //      CFO_Register reg;
    1355              : //      switch (link)
    1356              : //      {
    1357              : //              case CFO_Link_0:
    1358              : //                      reg = CFO_Register_TransmitByteCountDataLink0;
    1359              : //                      break;
    1360              : //              case CFO_Link_1:
    1361              : //                      reg = CFO_Register_TransmitByteCountDataLink1;
    1362              : //                      break;
    1363              : //              case CFO_Link_2:
    1364              : //                      reg = CFO_Register_TransmitByteCountDataLink2;
    1365              : //                      break;
    1366              : //              case CFO_Link_3:
    1367              : //                      reg = CFO_Register_TransmitByteCountDataLink3;
    1368              : //                      break;
    1369              : //              case CFO_Link_4:
    1370              : //                      reg = CFO_Register_TransmitByteCountDataLink4;
    1371              : //                      break;
    1372              : //              case CFO_Link_5:
    1373              : //                      reg = CFO_Register_TransmitByteCountDataLink5;
    1374              : //                      break;
    1375              : //              case CFO_Link_6:
    1376              : //                      reg = CFO_Register_TransmitByteCountDataLink6;
    1377              : //                      break;
    1378              : //              case CFO_Link_7:
    1379              : //                      reg = CFO_Register_TransmitByteCountDataLink7;
    1380              : //                      break;
    1381              : //              default: {
    1382              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1383              : //                      __SS_THROW__;
    1384              : //              }
    1385              : //      }
    1386              : //      return val.has_value() ? *val : ReadRegister_(reg);
    1387              : // }
    1388              : 
    1389              : // void CFOLib::CFO_Registers::ClearTransmitPacketCount(const CFO_Link_ID& link)
    1390              : // {
    1391              : //      CFO_Register reg;
    1392              : //      switch (link)
    1393              : //      {
    1394              : //              case CFO_Link_0:
    1395              : //                      reg = CFO_Register_TransmitPacketCountDataLink0;
    1396              : //                      break;
    1397              : //              case CFO_Link_1:
    1398              : //                      reg = CFO_Register_TransmitPacketCountDataLink1;
    1399              : //                      break;
    1400              : //              case CFO_Link_2:
    1401              : //                      reg = CFO_Register_TransmitPacketCountDataLink2;
    1402              : //                      break;
    1403              : //              case CFO_Link_3:
    1404              : //                      reg = CFO_Register_TransmitPacketCountDataLink3;
    1405              : //                      break;
    1406              : //              case CFO_Link_4:
    1407              : //                      reg = CFO_Register_TransmitPacketCountDataLink4;
    1408              : //                      break;
    1409              : //              case CFO_Link_5:
    1410              : //                      reg = CFO_Register_TransmitPacketCountDataLink5;
    1411              : //                      break;
    1412              : //              case CFO_Link_6:
    1413              : //                      reg = CFO_Register_TransmitPacketCountDataLink6;
    1414              : //                      break;
    1415              : //              case CFO_Link_7:
    1416              : //                      reg = CFO_Register_TransmitPacketCountDataLink7;
    1417              : //                      break;
    1418              : //              default: {
    1419              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1420              : //                      __SS_THROW__;
    1421              : //              }
    1422              : //      }
    1423              : //      WriteRegister_(0, reg);
    1424              : // }
    1425              : 
    1426              : // uint32_t CFOLib::CFO_Registers::ReadTransmitPacketCount(const CFO_Link_ID& link, std::optional<uint32_t> val)
    1427              : // {
    1428              : //      CFO_Register reg;
    1429              : //      switch (link)
    1430              : //      {
    1431              : //              case CFO_Link_0:
    1432              : //                      reg = CFO_Register_TransmitPacketCountDataLink0;
    1433              : //                      break;
    1434              : //              case CFO_Link_1:
    1435              : //                      reg = CFO_Register_TransmitPacketCountDataLink1;
    1436              : //                      break;
    1437              : //              case CFO_Link_2:
    1438              : //                      reg = CFO_Register_TransmitPacketCountDataLink2;
    1439              : //                      break;
    1440              : //              case CFO_Link_3:
    1441              : //                      reg = CFO_Register_TransmitPacketCountDataLink3;
    1442              : //                      break;
    1443              : //              case CFO_Link_4:
    1444              : //                      reg = CFO_Register_TransmitPacketCountDataLink4;
    1445              : //                      break;
    1446              : //              case CFO_Link_5:
    1447              : //                      reg = CFO_Register_TransmitPacketCountDataLink5;
    1448              : //                      break;
    1449              : //              case CFO_Link_6:
    1450              : //                      reg = CFO_Register_TransmitPacketCountDataLink6;
    1451              : //                      break;
    1452              : //              case CFO_Link_7:
    1453              : //                      reg = CFO_Register_TransmitPacketCountDataLink7;
    1454              : //                      break;
    1455              : //              default: {
    1456              : //                      __SS__ << "Illegal link index provided: " << link << __E__;
    1457              : //                      __SS_THROW__;
    1458              : //              }
    1459              : //      }
    1460              : //      return val.has_value() ? *val : ReadRegister_(reg);
    1461              : // }
    1462              : 
    1463            0 : uint32_t CFOLib::CFO_Registers::ReadReceiveRF0MarkerCount(std::optional<uint32_t> val)
    1464              : {
    1465            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_ReceiveRF0MarkerCount);
    1466            0 :         return static_cast<uint32_t>(data.to_ulong());
    1467              : }
    1468            0 : uint32_t CFOLib::CFO_Registers::ReadTransmitHeartbeatPacketCount(std::optional<uint32_t> val)
    1469              : {
    1470            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_TransmitHeartbeatPacketCount);
    1471            0 :         return static_cast<uint32_t>(data.to_ulong());
    1472              : }
    1473            0 : uint32_t CFOLib::CFO_Registers::ReadTransmitEventWindowMarkerCount(std::optional<uint32_t> val)
    1474              : {
    1475            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFO_Register_TransmitEventWindowMarkerCount);
    1476            0 :         return static_cast<uint32_t>(data.to_ulong());
    1477              : }
    1478              : 
    1479            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveRF0MarkerCount()
    1480              : {
    1481            0 :         auto form = CreateFormatter(CFO_Register_ReceiveRF0MarkerCount);
    1482            0 :         form.description = "Receive RF0 Marker Count";
    1483            0 :         std::stringstream o;
    1484            0 :         o << "0x" << std::hex << ReadReceiveRF0MarkerCount(form.value);
    1485            0 :         form.vals.push_back(o.str());
    1486            0 :         return form;
    1487            0 : }
    1488              : 
    1489            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitHeartbeatPacketCount()
    1490              : {
    1491            0 :         auto form = CreateFormatter(CFO_Register_TransmitHeartbeatPacketCount);
    1492            0 :         form.description = "Transmit Heartbeat Packet Count";
    1493            0 :         std::stringstream o;
    1494            0 :         o << "0x" << std::hex << ReadTransmitHeartbeatPacketCount(form.value);
    1495            0 :         form.vals.push_back(o.str());
    1496            0 :         return form;
    1497            0 : }
    1498              : 
    1499            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitEventWindowMarkerCount()
    1500              : {
    1501            0 :         auto form = CreateFormatter(CFO_Register_TransmitEventWindowMarkerCount);
    1502            0 :         form.description = "Transmit Event Window Marker Count";
    1503            0 :         std::stringstream o;
    1504            0 :         o << "0x" << std::hex << ReadTransmitEventWindowMarkerCount(form.value);
    1505            0 :         form.vals.push_back(o.str());
    1506            0 :         return form;
    1507            0 : }
    1508              : 
    1509              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink0()
    1510              : // {
    1511              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink0);
    1512              : //      form.description = "Receive Byte Count: Link 0";
    1513              : //      std::stringstream o;
    1514              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_0, form.value);
    1515              : //      form.vals.push_back(o.str());
    1516              : //      return form;
    1517              : // }
    1518              : 
    1519              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink1()
    1520              : // {
    1521              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink1);
    1522              : //      form.description = "Receive Byte Count: Link 1";
    1523              : //      std::stringstream o;
    1524              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_1, form.value);
    1525              : //      form.vals.push_back(o.str());
    1526              : //      return form;
    1527              : // }
    1528              : 
    1529              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink2()
    1530              : // {
    1531              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink2);
    1532              : //      form.description = "Receive Byte Count: Link 2";
    1533              : //      std::stringstream o;
    1534              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_2, form.value);
    1535              : //      form.vals.push_back(o.str());
    1536              : //      return form;
    1537              : // }
    1538              : 
    1539              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink3()
    1540              : // {
    1541              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink3);
    1542              : //      form.description = "Receive Byte Count: Link 3";
    1543              : //      std::stringstream o;
    1544              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_3, form.value);
    1545              : //      form.vals.push_back(o.str());
    1546              : //      return form;
    1547              : // }
    1548              : 
    1549              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink4()
    1550              : // {
    1551              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink4);
    1552              : //      form.description = "Receive Byte Count: Link 4";
    1553              : //      std::stringstream o;
    1554              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_4, form.value);
    1555              : //      form.vals.push_back(o.str());
    1556              : //      return form;
    1557              : // }
    1558              : 
    1559              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink5()
    1560              : // {
    1561              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink5);
    1562              : //      form.description = "Receive Byte Count: Link 5";
    1563              : //      std::stringstream o;
    1564              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_5, form.value);
    1565              : //      form.vals.push_back(o.str());
    1566              : //      return form;
    1567              : // }
    1568              : 
    1569              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink6()
    1570              : // {
    1571              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink6);
    1572              : //      form.description = "Receive Byte Count: Link 6";
    1573              : //      std::stringstream o;
    1574              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_6, form.value);
    1575              : //      form.vals.push_back(o.str());
    1576              : //      return form;
    1577              : // }
    1578              : 
    1579              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceiveByteCountLink7()
    1580              : // {
    1581              : //      auto form = CreateFormatter(CFO_Register_ReceiveByteCountDataLink7);
    1582              : //      form.description = "Receive Byte Count: Link 7";
    1583              : //      std::stringstream o;
    1584              : //      o << "0x" << std::hex << ReadReceiveByteCount(CFO_Link_7, form.value);
    1585              : //      form.vals.push_back(o.str());
    1586              : //      return form;
    1587              : // }
    1588              : 
    1589              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink0()
    1590              : // {
    1591              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink0);
    1592              : //      form.description = "Receive Packet Count: Link 0";
    1593              : //      std::stringstream o;
    1594              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_0);
    1595              : //      form.vals.push_back(o.str());
    1596              : //      return form;
    1597              : // }
    1598              : 
    1599              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink1()
    1600              : // {
    1601              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink1);
    1602              : //      form.description = "Receive Packet Count: Link 1";
    1603              : //      std::stringstream o;
    1604              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_1);
    1605              : //      form.vals.push_back(o.str());
    1606              : //      return form;
    1607              : // }
    1608              : 
    1609              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink2()
    1610              : // {
    1611              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink2);
    1612              : //      form.description = "Receive Packet Count: Link 2";
    1613              : //      std::stringstream o;
    1614              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_2);
    1615              : //      form.vals.push_back(o.str());
    1616              : //      return form;
    1617              : // }
    1618              : 
    1619              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink3()
    1620              : // {
    1621              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink3);
    1622              : //      form.description = "Receive Packet Count: Link 3";
    1623              : //      std::stringstream o;
    1624              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_3);
    1625              : //      form.vals.push_back(o.str());
    1626              : //      return form;
    1627              : // }
    1628              : 
    1629              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink4()
    1630              : // {
    1631              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink4);
    1632              : //      form.description = "Receive Packet Count: Link 4";
    1633              : //      std::stringstream o;
    1634              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_4);
    1635              : //      form.vals.push_back(o.str());
    1636              : //      return form;
    1637              : // }
    1638              : 
    1639              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink5()
    1640              : // {
    1641              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink5);
    1642              : //      form.description = "Receive Packet Count: Link 5";
    1643              : //      std::stringstream o;
    1644              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_5);
    1645              : //      form.vals.push_back(o.str());
    1646              : //      return form;
    1647              : // }
    1648              : 
    1649              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink6()
    1650              : // {
    1651              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink6);
    1652              : //      form.description = "Receive Packet Count: Link 6";
    1653              : //      std::stringstream o;
    1654              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_6);
    1655              : //      form.vals.push_back(o.str());
    1656              : //      return form;
    1657              : // }
    1658              : 
    1659              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatReceivePacketCountLink7()
    1660              : // {
    1661              : //      auto form = CreateFormatter(CFO_Register_ReceivePacketCountDataLink7);
    1662              : //      form.description = "Receive Packet Count: Link 7";
    1663              : //      std::stringstream o;
    1664              : //      o << "0x" << std::hex << ReadReceivePacketCount(CFO_Link_7);
    1665              : //      form.vals.push_back(o.str());
    1666              : //      return form;
    1667              : // }
    1668              : 
    1669              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink0()
    1670              : // {
    1671              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink0);
    1672              : //      form.description = "Transmit Byte Count: Link 0";
    1673              : //      std::stringstream o;
    1674              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_0);
    1675              : //      form.vals.push_back(o.str());
    1676              : //      return form;
    1677              : // }
    1678              : 
    1679              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink1()
    1680              : // {
    1681              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink1);
    1682              : //      form.description = "Transmit Byte Count: Link 1";
    1683              : //      std::stringstream o;
    1684              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_1);
    1685              : //      form.vals.push_back(o.str());
    1686              : //      return form;
    1687              : // }
    1688              : 
    1689              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink2()
    1690              : // {
    1691              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink2);
    1692              : //      form.description = "Transmit Byte Count: Link 2";
    1693              : //      std::stringstream o;
    1694              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_2);
    1695              : //      form.vals.push_back(o.str());
    1696              : //      return form;
    1697              : // }
    1698              : 
    1699              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink3()
    1700              : // {
    1701              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink3);
    1702              : //      form.description = "Transmit Byte Count: Link 3";
    1703              : //      std::stringstream o;
    1704              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_3);
    1705              : //      form.vals.push_back(o.str());
    1706              : //      return form;
    1707              : // }
    1708              : 
    1709              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink4()
    1710              : // {
    1711              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink4);
    1712              : //      form.description = "Transmit Byte Count: Link 4";
    1713              : //      std::stringstream o;
    1714              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_4);
    1715              : //      form.vals.push_back(o.str());
    1716              : //      return form;
    1717              : // }
    1718              : 
    1719              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink5()
    1720              : // {
    1721              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink5);
    1722              : //      form.description = "Transmit Byte Count: Link 5";
    1723              : //      std::stringstream o;
    1724              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_5);
    1725              : //      form.vals.push_back(o.str());
    1726              : //      return form;
    1727              : // }
    1728              : 
    1729              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink6()
    1730              : // {
    1731              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink6);
    1732              : //      form.description = "Transmit Byte Count: Link 6";
    1733              : //      std::stringstream o;
    1734              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_6);
    1735              : //      form.vals.push_back(o.str());
    1736              : //      return form;
    1737              : // }
    1738              : 
    1739              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTramsitByteCountLink7()
    1740              : // {
    1741              : //      auto form = CreateFormatter(CFO_Register_TransmitByteCountDataLink7);
    1742              : //      form.description = "Transmit Byte Count: Link 7";
    1743              : //      std::stringstream o;
    1744              : //      o << "0x" << std::hex << ReadTransmitByteCount(CFO_Link_7);
    1745              : //      form.vals.push_back(o.str());
    1746              : //      return form;
    1747              : // }
    1748              : 
    1749              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink0()
    1750              : // {
    1751              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink0);
    1752              : //      form.description = "Transmit Packet Count: Link 0";
    1753              : //      std::stringstream o;
    1754              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_0);
    1755              : //      form.vals.push_back(o.str());
    1756              : //      return form;
    1757              : // }
    1758              : 
    1759              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink1()
    1760              : // {
    1761              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink1);
    1762              : //      form.description = "Transmit Packet Count: Link 1";
    1763              : //      std::stringstream o;
    1764              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_1);
    1765              : //      form.vals.push_back(o.str());
    1766              : //      return form;
    1767              : // }
    1768              : 
    1769              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink2()
    1770              : // {
    1771              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink2);
    1772              : //      form.description = "Transmit Packet Count: Link 2";
    1773              : //      std::stringstream o;
    1774              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_2);
    1775              : //      form.vals.push_back(o.str());
    1776              : //      return form;
    1777              : // }
    1778              : 
    1779              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink3()
    1780              : // {
    1781              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink3);
    1782              : //      form.description = "Transmit Packet Count: Link 3";
    1783              : //      std::stringstream o;
    1784              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_3);
    1785              : //      form.vals.push_back(o.str());
    1786              : //      return form;
    1787              : // }
    1788              : 
    1789              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink4()
    1790              : // {
    1791              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink4);
    1792              : //      form.description = "Transmit Packet Count: Link 4";
    1793              : //      std::stringstream o;
    1794              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_4);
    1795              : //      form.vals.push_back(o.str());
    1796              : //      return form;
    1797              : // }
    1798              : 
    1799              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink5()
    1800              : // {
    1801              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink5);
    1802              : //      form.description = "Transmit Packet Count: Link 5";
    1803              : //      std::stringstream o;
    1804              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_5);
    1805              : //      form.vals.push_back(o.str());
    1806              : //      return form;
    1807              : // }
    1808              : 
    1809              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink6()
    1810              : // {
    1811              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink6);
    1812              : //      form.description = "Transmit Packet Count: Link 6";
    1813              : //      std::stringstream o;
    1814              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_6);
    1815              : //      form.vals.push_back(o.str());
    1816              : //      return form;
    1817              : // }
    1818              : 
    1819              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatTransmitPacketCountLink7()
    1820              : // {
    1821              : //      auto form = CreateFormatter(CFO_Register_TransmitPacketCountDataLink7);
    1822              : //      form.description = "Transmit Packet Count: Link 7";
    1823              : //      std::stringstream o;
    1824              : //      o << "0x" << std::hex << ReadTransmitPacketCount(CFO_Link_7);
    1825              : //      form.vals.push_back(o.str());
    1826              : //      return form;
    1827              : // }
    1828              : 
    1829              : // DMA Address Registers
    1830            0 : void CFOLib::CFO_Registers::SetDMAWriteStartAddress(const uint32_t& address)
    1831              : {
    1832            0 :         WriteRegister_(address, CFO_Register_DDRMemoryDMAWriteStartAddress);
    1833            0 : }
    1834              : 
    1835            0 : uint32_t CFOLib::CFO_Registers::ReadDMAWriteStartAddress(std::optional<uint32_t> val)
    1836              : {
    1837            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_DDRMemoryDMAWriteStartAddress);
    1838              : }
    1839              : 
    1840            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatDMAWriteStartAddress()
    1841              : {
    1842            0 :         auto form = CreateFormatter(CFO_Register_DDRMemoryDMAWriteStartAddress);
    1843            0 :         form.description = "DDR Memory DMA Write Start Address";
    1844            0 :         form.vals.push_back(std::to_string(ReadDMAWriteStartAddress(form.value)));
    1845            0 :         return form;
    1846            0 : }
    1847              : 
    1848            0 : void CFOLib::CFO_Registers::SetDMAReadStartAddress(const uint32_t& address)
    1849              : {
    1850            0 :         WriteRegister_(address, CFO_Register_DDRMemoryDMAReadStartAddress);
    1851            0 : }
    1852              : 
    1853            0 : uint32_t CFOLib::CFO_Registers::ReadDMAReadStartAddress(std::optional<uint32_t> val)
    1854              : {
    1855            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_DDRMemoryDMAReadStartAddress);
    1856              : }
    1857              : 
    1858            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatDMAReadStartAddress()
    1859              : {
    1860            0 :         auto form = CreateFormatter(CFO_Register_DDRMemoryDMAWriteStartAddress);
    1861            0 :         form.description = "DDR Memory DMA Read Start Address";
    1862            0 :         form.vals.push_back(std::to_string(ReadDMAReadStartAddress(form.value)));
    1863            0 :         return form;
    1864            0 : }
    1865              : 
    1866            0 : void CFOLib::CFO_Registers::SetDMAReadByteCount(const uint32_t& bytes)
    1867              : {
    1868            0 :         WriteRegister_(bytes, CFO_Register_DDRMemoryDMAReadByteCount);
    1869            0 : }
    1870              : 
    1871            0 : uint32_t CFOLib::CFO_Registers::ReadDMAReadByteCount(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(CFO_Register_DDRMemoryDMAReadByteCount); }
    1872              : 
    1873            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatDMAReadByteCount()
    1874              : {
    1875            0 :         auto form = CreateFormatter(CFO_Register_DDRMemoryDMAWriteStartAddress);
    1876            0 :         form.description = "DDR Memory DMA Read Byte Count/Enable";
    1877            0 :         form.vals.push_back(std::to_string(ReadDMAReadByteCount(form.value)));
    1878            0 :         return form;
    1879            0 : }
    1880              : 
    1881            0 : void CFOLib::CFO_Registers::SetRunPlanBeamOnBaseAddress(const uint32_t& address)
    1882              : {
    1883            0 :         WriteRegister_(address, CFO_Register_RunPlanBeamOnBaseAddress);
    1884            0 : }
    1885              : 
    1886            0 : uint32_t CFOLib::CFO_Registers::ReadRunPlanBeamOnBaseAddress(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(CFO_Register_RunPlanBeamOnBaseAddress); }
    1887              : 
    1888            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanBeamOnBaseAddress()
    1889              : {
    1890            0 :         auto form = CreateFormatter(CFO_Register_RunPlanBeamOnBaseAddress);
    1891            0 :         form.description = "DDR Memory Beam On Base Address";
    1892            0 :         form.vals.push_back(std::to_string(ReadRunPlanBeamOnBaseAddress(form.value)));
    1893            0 :         return form;
    1894            0 : }
    1895              : 
    1896            0 : void CFOLib::CFO_Registers::SetRunPlanBeamOffBaseAddress(const uint32_t& address)
    1897              : {
    1898            0 :         WriteRegister_(address, CFO_Register_RunPlanBeamOffBaseAddress);
    1899            0 : }
    1900              : 
    1901            0 : uint32_t CFOLib::CFO_Registers::ReadRunPlanBeamOffBaseAddress(std::optional<uint32_t> val)
    1902              : {
    1903            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_RunPlanBeamOffBaseAddress);
    1904              : }
    1905              : 
    1906            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanBeamOffBaseAddress()
    1907              : {
    1908            0 :         auto form = CreateFormatter(CFO_Register_RunPlanBeamOffBaseAddress);
    1909            0 :         form.description = "DDR Memory Beam Off Base Address";
    1910            0 :         form.vals.push_back(std::to_string(ReadRunPlanBeamOffBaseAddress()));
    1911            0 :         return form;
    1912            0 : }
    1913              : 
    1914            0 : void CFOLib::CFO_Registers::SetRunPlanData(const std::string& inputData, const uint32_t& runPlanBaseAddress)
    1915              : {
    1916            0 :         __COUTTV__(inputData.size());
    1917            0 :         __COUT__ << "Writing run plan of size " << inputData.size() << " to base address 0x" << std::hex << std::setw(8) << std::setfill('0') << runPlanBaseAddress << __E__;
    1918              : 
    1919            0 :         auto dataPtr = reinterpret_cast<const uint8_t*>(&inputData[0]);
    1920              : 
    1921              :         // primary run plan write loop
    1922            0 :         WriteRegister_(runPlanBaseAddress, CFO_Register_RunPlan_Address);  // resets run plan BRAM write address
    1923            0 :         for (uint32_t l = 0; l < inputData.size(); l += 4)
    1924              :         {
    1925              :                 // CFO_Register_RunPlan_Address = 0x9314,
    1926              :                 // CFO_Register_RunPlan_Data = 0x9318,
    1927            0 :                 WriteRegister_(*((uint32_t*)(&(dataPtr[l]))), CFO_Register_RunPlan_Data);  // write data then increment BRAM address
    1928            0 :                 __COUTT__ << std::hex << std::setw(8) << std::setfill('0') << "addr 0x" << (runPlanBaseAddress + l / 4) << " data 0x" << *((uint32_t*)(&(dataPtr[l]))) << __E__;
    1929              :         }  // end primary run plan write loop
    1930              : 
    1931            0 :         __COUT__ << "Verifying run plan of size " << inputData.size() << " to base address 0x" << std::hex << std::setw(8) << std::setfill('0') << runPlanBaseAddress << __E__;
    1932              :         // now verify run plan w/readback (throws exception on mismatch)
    1933            0 :         CompareRunPlanData(inputData, runPlanBaseAddress);
    1934              : 
    1935            0 : }  // end SetRunPlanData()
    1936              : 
    1937              : /// @brief  Read back run plan data from BRAM and compare to input data for validation.
    1938              : ///             Note that the run plan BRAM read address auto-increments with each read, so we just need to set it once at the beginning of the function.
    1939              : ///             If mismatches has a value, it will be filled with a map of mismatches instead of throwing an exception on the first mismatch.
    1940              : ///             Otherwise (std::nullopt), an exception will be thrown on the first mismatch with details of the failure.
    1941              : /// @param inputData  The binary run plan data to compare against the readback.
    1942              : /// @param runPlanBaseAddress  The base BRAM address at which the run plan was written.
    1943              : /// @param mismatches  Optional reference to a map that will be filled with any mismatches found, where the key is the
    1944              : ///             address of the mismatch and the value is a pair of (expected, actual) data values.
    1945              : ///             Pass std::nullopt (default) to throw an exception on the first mismatch instead of collecting them.
    1946              : /// @param andMasks  Optional reference to a vector that will be filled with the 48-bit mask values found in
    1947              : ///             AND_MODE_BITS instructions during the readback scan. Pass std::nullopt (default) to skip collection.
    1948              : /// @param orMasks   Optional reference to a vector that will be filled with the 48-bit mask values found in
    1949              : ///             OR_MODE_BITS instructions during the readback scan. Pass std::nullopt (default) to skip collection.
    1950            0 : void CFOLib::CFO_Registers::CompareRunPlanData(const std::string& inputData, const uint32_t& runPlanBaseAddress,
    1951              :                                                                                            std::optional<std::reference_wrapper<std::map<uint32_t /* address */,
    1952              :                                                                                                                                                                                          std::pair<uint32_t /* expected */,
    1953              :                                                                                                                                                                                                            uint32_t /* actual */>>>>
    1954              :                                                                                                    mismatches,
    1955              :                                                                                            std::optional<std::reference_wrapper<std::vector<uint64_t>>> andMasks /* = std::nullopt */,
    1956              :                                                                                            std::optional<std::reference_wrapper<std::vector<uint64_t>>> orMasks /* = std::nullopt */)
    1957              : {
    1958            0 :         auto dataPtr = reinterpret_cast<const uint8_t*>(&inputData[0]);
    1959              : 
    1960            0 :         WriteRegister_(runPlanBaseAddress, CFO_Register_RunPlan_Address);  // resets run plan BRAM write address
    1961            0 :         uint32_t val, lastVal = 0;
    1962            0 :         for (uint32_t l = 0; l < inputData.size(); l += 4)
    1963              :         {
    1964            0 :                 val = ReadRegister_(CFO_Register_RunPlan_Data);
    1965              : 
    1966            0 :                 __COUTT__ << std::hex << std::setw(8) << std::setfill('0') << "addr 0x" << (runPlanBaseAddress + l / 4) << " data 0x" << *((uint32_t*)(&(dataPtr[l]))) << " =? rdata 0x" << val << __E__;
    1967              : 
    1968            0 :                 if ((andMasks || orMasks) && l % 8 == 4)  // check opcodes
    1969              :                 {
    1970            0 :                         uint8_t opCode = ((*((uint32_t*)(&(dataPtr[l])))) >> 24) & 0xFF;
    1971            0 :                         if (andMasks && opCode == (uint8_t)CFOLib::CFO_Compiler::CFO_INSTR::AND_MODE_BITS)
    1972              :                         {
    1973            0 :                                 andMasks->get().push_back((uint64_t)lastVal | ((uint64_t)(val & 0xFFFF) << 32));
    1974            0 :                                 __COUTT__ << "Found AND line = " << l / 8 << " --> 0x" << std::hex << andMasks->get().back() << __E__;
    1975              :                         }
    1976            0 :                         if (orMasks && opCode == (uint8_t)CFOLib::CFO_Compiler::CFO_INSTR::OR_MODE_BITS)
    1977              :                         {
    1978            0 :                                 orMasks->get().push_back((uint64_t)lastVal | ((uint64_t)(val & 0xFFFF) << 32));
    1979            0 :                                 __COUTT__ << "Found OR line = " << l / 8 << " --> 0x" << std::hex << orMasks->get().back() << __E__;
    1980              :                         }
    1981              :                 }
    1982              : 
    1983            0 :                 if (val != *((uint32_t*)(&(dataPtr[l]))))
    1984              :                 {
    1985            0 :                         uint8_t opCode = -1;
    1986            0 :                         if (l % 8 == 4)
    1987            0 :                                 opCode = ((*((uint32_t*)(&(dataPtr[l])))) >> 24) & 0xFF;
    1988            0 :                         else if (l + 4 < inputData.size())
    1989            0 :                                 opCode = ((*((uint32_t*)(&(dataPtr[l + 4])))) >> 24) & 0xFF;
    1990            0 :                         if (opCode == (uint8_t)CFOLib::CFO_Compiler::CFO_INSTR::OR_SINGLESHOT_MODE_BITS)
    1991              :                         {
    1992            0 :                                 if (l % 8 == 4 && opCode == (val >> 24))  // if opcode matches, ignore mismatch since single-shot mode bit instructions fire once and then clear 48-bit value
    1993              :                                 {
    1994            0 :                                         __COUTT__ << "Ignoring mismatch at line #" << l / 8 << " for OR_SINGLESHOT_MODE_BITS instruction since opcode matches and data auto-clears after firing." << __E__;
    1995            0 :                                         continue;
    1996            0 :                                 }
    1997            0 :                                 if (l % 8 == 0)
    1998              :                                 {
    1999            0 :                                         __COUTT__ << "Ignoring mismatch at line #" << l / 8 << " for OR_SINGLESHOT_MODE_BITS instruction since opcode matches for this data and data auto-clears after firing." << __E__;
    2000            0 :                                         continue;
    2001            0 :                                 }
    2002              :                         }
    2003              : 
    2004            0 :                         __SS__ << "Run plan validation failed at line #" << l / 8 << " "
    2005            0 :                                    << "addr 0x" << std::hex << std::setw(8) << std::setfill('0') << (runPlanBaseAddress + l / 4)
    2006            0 :                                    << " expected data 0x" << std::hex << std::setw(8) << std::setfill('0') << *((uint32_t*)(&(dataPtr[l])))
    2007            0 :                                    << " != readback data 0x" << std::hex << std::setw(8) << std::setfill('0') << val << __E__;
    2008            0 :                         if (!mismatches)
    2009            0 :                                 __SS_THROW__;
    2010              : 
    2011            0 :                         __COUTT__ << ss.str() << __E__;
    2012            0 :                         mismatches->get()[runPlanBaseAddress + l / 4] = std::make_pair(*((uint32_t*)(&(dataPtr[l]))), val);
    2013            0 :                 }
    2014              : 
    2015            0 :                 lastVal = val;
    2016              :         }  // end run plan validation
    2017              : 
    2018            0 : }  // end CompareRunPlanData()
    2019              : 
    2020              : /// Read current tag bits from two registers and concatenate the full 48-bit value
    2021            0 : uint64_t CFOLib::CFO_Registers::ReadRunPlanCurrentTag()
    2022              : {
    2023            0 :         uint64_t val = ReadRegister_(CFO_Register_RunPlan_EventTag0);
    2024            0 :         val |= (uint64_t(ReadRegister_(CFO_Register_RunPlan_EventTag1))) << 32;
    2025            0 :         return val;
    2026              : }  // end ReadRunPlanCurrentTag()
    2027              : 
    2028            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanCurrentTag()
    2029              : {
    2030            0 :         uint64_t currentTag = ReadRunPlanCurrentTag();
    2031            0 :         auto form = CreateFormatter(CFO_Register_RunPlan_EventTag1, false /* getValue */);
    2032            0 :         form.value = uint32_t(currentTag >> 32);  // show high 32-bits of tag in hex value field
    2033            0 :         form.description = "Run Plan Current Tag";
    2034              :         {
    2035            0 :                 std::stringstream oss;
    2036            0 :                 oss << "0x" << std::hex << std::setw(8) << std::setfill('0') << uint32_t(currentTag);  // show hex format low 32-bits of tag
    2037            0 :                 form.vals.push_back(oss.str());
    2038            0 :         }
    2039              :         {  // show full 64-bit number
    2040            0 :                 std::stringstream oss;
    2041            0 :                 oss << std::dec << currentTag << " " << std::scientific << static_cast<double>(currentTag) << " (0x" << std::hex << currentTag << ")";
    2042            0 :                 form.vals.push_back(oss.str());
    2043            0 :         }
    2044            0 :         return form;
    2045            0 : }  // end FormatRunPlanCurrentTag()
    2046              : 
    2047              : /// Read current mode bits from two registers and concatenate the full 48-bit value
    2048            0 : uint64_t CFOLib::CFO_Registers::ReadRunPlanCurrentMode()
    2049              : {
    2050            0 :         uint64_t val = ReadRegister_(CFO_Register_RunPlan_EventMode0);
    2051            0 :         val |= (uint64_t(ReadRegister_(CFO_Register_RunPlan_EventMode1))) << 32;
    2052            0 :         return val;
    2053              : }  // end ReadRunPlanCurrentMode()
    2054              : 
    2055            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanCurrentMode()
    2056              : {
    2057            0 :         auto form = CreateFormatter(CFO_Register_RunPlan_EventMode0, false /* getValue */);
    2058            0 :         form.description = "Run Plan Current Mode";
    2059              : 
    2060            0 :         uint64_t mode = ReadRunPlanCurrentMode();
    2061              : 
    2062              :         // -- parse for each subsystem according docdb 4914 --
    2063              :         // Mode Packet Definition:
    2064              :         // Event Mode Byte 1 (Resrv’d Trk)    Event Mode Byte 0 [7:3]         Pattern Mode [2:1]      Injection Data Source [0]
    2065              :         // Event Mode Byte 3 (Resrv’d CRV)    Event Mode Byte 2 (Resrv’d Calo) [7:1]        Calo Laser Injection [0]
    2066              :         // Delivery Ring RF-0 Marker TDC [15:8] Resrv’d (TEM) [7:6] (STM) [5:4]       Subrun Handling [3:1]   On-spill Flag [0]
    2067              :         //
    2068              :         // The high Event Mode bit, for example bit index 7 of a subsystem’s mode byte (or bit 1 of a subsystem’s 2-bit mode,
    2069              :         // is considered the active bit.  If set, the corresponding subsystem is expected to record data for that Event Window.
    2070              : 
    2071            0 :         std::map<std::string, uint16_t> subsystemModeMap;
    2072            0 :         subsystemModeMap["Tracker"] = (mode >> 8) & 0xFF;  // bits [7:0] of Event Mode Byte-1
    2073            0 :         subsystemModeMap["Calo"] = (mode >> 16) & 0xFF;    // bits [7:0] of Event Mode Byte-2
    2074            0 :         subsystemModeMap["CRV"] = (mode >> 32) & 0xFF;     // bits [7:0] of Event Mode Byte-3
    2075            0 :         subsystemModeMap["STM"] = (mode >> 36) & 0x3;      // bits [1:0] of Event Mode Byte-4 upper nibble
    2076            0 :         subsystemModeMap["ExtMon"] = (mode >> 38) & 0x3;   // bits [3:2] of Event Mode Byte-4 upper nibble
    2077              : 
    2078            0 :         subsystemModeMap["Tracker active"] = (subsystemModeMap["Tracker"] >> 7) & 1;  // high Event Mode bit is active bit
    2079            0 :         subsystemModeMap["Calo active"] = (subsystemModeMap["Calo"] >> 7) & 1;        // high Event Mode bit is active bit
    2080            0 :         subsystemModeMap["CRV active"] = (subsystemModeMap["CRV"] >> 7) & 1;          // high Event Mode bit is active bit
    2081            0 :         subsystemModeMap["STM active"] = (subsystemModeMap["STM"] >> 1) & 1;          // high Event Mode bit is active bit
    2082            0 :         subsystemModeMap["ExtMon active"] = (subsystemModeMap["ExtMon"] >> 1) & 1;    // high Event Mode bit is active bit
    2083              : 
    2084            0 :         std::stringstream oss;
    2085            0 :         oss << "0x" << std::hex << std::setw(8) << std::setfill('0') << ReadRegister_(CFO_Register_RunPlan_EventMode0);
    2086            0 :         form.vals.push_back(oss.str());             // show hex format low 32-bits of mode
    2087            0 :         form.vals.push_back(std::to_string(mode));  // show decimal value
    2088            0 :         form.vals.push_back("");                    // spacer for readability
    2089            0 :         for (auto pair : subsystemModeMap)
    2090              :         {
    2091            0 :                 if (pair.first.find("active") != std::string::npos) continue;
    2092              : 
    2093            0 :                 std::stringstream o;
    2094            0 :                 if (pair.first.find("STM") != std::string::npos || pair.first.find("ExtMon") != std::string::npos)
    2095            0 :                         o << pair.first + ": " << std::string(12 - pair.first.size(), ' ') <<  // pad for alignment
    2096            0 :                                 "b" << std::bitset<2>(pair.second) << std::string(6, ' ') << " (0x" << std::hex << pair.second << ")" << (subsystemModeMap[pair.first + " active"] ? " in" : " out");
    2097              :                 else
    2098            0 :                         o << pair.first + ": " << std::string(12 - pair.first.size(), ' ') <<  // pad for alignment
    2099            0 :                                 "b" << std::bitset<8>(pair.second) << " (0x" << std::hex << pair.second << ")" << (subsystemModeMap[pair.first + " active"] ? " in" : " out");
    2100            0 :                 form.vals.push_back(o.str());
    2101            0 :         }
    2102            0 :         return form;
    2103            0 : }  // end FormatRunPlanCurrentMode()
    2104              : 
    2105              : // Run Plan Subrun Event Limit Register
    2106            0 : void CFOLib::CFO_Registers::SetRunPlanSubrunEvtLimit(uint32_t limit)
    2107              : {
    2108            0 :         WriteRegister_(limit, CFO_Register_RunPlanSubrunEvtLimit);
    2109            0 : }
    2110              : 
    2111            0 : uint32_t CFOLib::CFO_Registers::ReadRunPlanSubrunEvtLimit(std::optional<uint32_t> val)
    2112              : {
    2113            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_RunPlanSubrunEvtLimit);
    2114              : }
    2115              : 
    2116            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanSubrunEvtLimit()
    2117              : {
    2118            0 :         auto form = CreateFormatter(CFO_Register_RunPlanSubrunEvtLimit);
    2119            0 :         form.description = "Run Plan Subrun Event Limit";
    2120            0 :         form.vals.push_back(std::to_string(ReadRunPlanSubrunEvtLimit(form.value)));
    2121            0 :         return form;
    2122            0 : }
    2123              : 
    2124              : // Run Plan Subrun Prediction Offset Register
    2125            0 : void CFOLib::CFO_Registers::SetRunPlanSubrunPredOffset(uint32_t offset)
    2126              : {
    2127            0 :         WriteRegister_(offset, CFO_Register_RunPlanSubrunPredOffset);
    2128            0 : }
    2129              : 
    2130            0 : uint32_t CFOLib::CFO_Registers::ReadRunPlanSubrunPredOffset(std::optional<uint32_t> val)
    2131              : {
    2132            0 :         return val.has_value() ? *val : ReadRegister_(CFO_Register_RunPlanSubrunPredOffset);
    2133              : }
    2134              : 
    2135            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatRunPlanSubrunPredOffset()
    2136              : {
    2137            0 :         auto form = CreateFormatter(CFO_Register_RunPlanSubrunPredOffset);
    2138            0 :         form.description = "Run Plan Subrun Prediction Offset";
    2139            0 :         form.vals.push_back(std::to_string(ReadRunPlanSubrunPredOffset(form.value)));
    2140            0 :         return form;
    2141            0 : }
    2142              : 
    2143              : // Firefly CSR Register
    2144            0 : bool CFOLib::CFO_Registers::ReadFireflyTXRXPresent(std::optional<uint32_t> val)
    2145              : {
    2146            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2147            0 :         return dataSet[26];
    2148              : }
    2149              : 
    2150            0 : bool CFOLib::CFO_Registers::ReadFireflyRXPresent(std::optional<uint32_t> val)
    2151              : {
    2152            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2153            0 :         return dataSet[25];
    2154              : }
    2155              : 
    2156            0 : bool CFOLib::CFO_Registers::ReadFireflyTXPresent(std::optional<uint32_t> val)
    2157              : {
    2158            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2159            0 :         return dataSet[24];
    2160              : }
    2161              : 
    2162            0 : bool CFOLib::CFO_Registers::ReadFireflyTXRXInterrupt(std::optional<uint32_t> val)
    2163              : {
    2164            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2165            0 :         return dataSet[18];
    2166              : }
    2167              : 
    2168            0 : bool CFOLib::CFO_Registers::ReadFireflyRXInterrupt(std::optional<uint32_t> val)
    2169              : {
    2170            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2171            0 :         return dataSet[17];
    2172              : }
    2173              : 
    2174            0 : bool CFOLib::CFO_Registers::ReadFireflyTXInterrupt(std::optional<uint32_t> val)
    2175              : {
    2176            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2177            0 :         return dataSet[16];
    2178              : }
    2179              : 
    2180            0 : void CFOLib::CFO_Registers::SetFireflyTXRXSelect(bool select)
    2181              : {
    2182            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2183            0 :         dataSet[10] = select;
    2184            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2185            0 : }
    2186              : 
    2187            0 : void CFOLib::CFO_Registers::SetFireflyRXSelect(bool select)
    2188              : {
    2189            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2190            0 :         dataSet[9] = select;
    2191            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2192            0 : }
    2193              : 
    2194            0 : void CFOLib::CFO_Registers::SetFireflyTXSelect(bool select)
    2195              : {
    2196            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2197            0 :         dataSet[8] = select;
    2198            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2199            0 : }
    2200              : 
    2201            0 : bool CFOLib::CFO_Registers::ReadFireflyTXRXSelect(std::optional<uint32_t> val)
    2202              : {
    2203            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2204            0 :         return dataSet[10];
    2205              : }
    2206              : 
    2207            0 : bool CFOLib::CFO_Registers::ReadFireflyRXSelect(std::optional<uint32_t> val)
    2208              : {
    2209            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2210            0 :         return dataSet[9];
    2211              : }
    2212              : 
    2213            0 : bool CFOLib::CFO_Registers::ReadFireflyTXSelect(std::optional<uint32_t> val)
    2214              : {
    2215            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2216            0 :         return dataSet[8];
    2217              : }
    2218              : 
    2219            0 : void CFOLib::CFO_Registers::SetFireflyTXRXReset(bool reset)
    2220              : {
    2221            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2222            0 :         dataSet[2] = reset;
    2223            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2224            0 : }
    2225              : 
    2226            0 : void CFOLib::CFO_Registers::SetFireflyRXReset(bool reset)
    2227              : {
    2228            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2229            0 :         dataSet[1] = reset;
    2230            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2231            0 : }
    2232              : 
    2233            0 : void CFOLib::CFO_Registers::SetFireflyTXReset(bool reset)
    2234              : {
    2235            0 :         std::bitset<32> dataSet = ReadRegister_(CFO_Register_FireflyCSRRegister);
    2236            0 :         dataSet[0] = reset;
    2237            0 :         WriteRegister_(dataSet.to_ulong(), CFO_Register_FireflyCSRRegister);
    2238            0 : }
    2239              : 
    2240            0 : bool CFOLib::CFO_Registers::ReadFireflyTXRXReset(std::optional<uint32_t> val)
    2241              : {
    2242            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2243            0 :         return dataSet[2];
    2244              : }
    2245              : 
    2246            0 : bool CFOLib::CFO_Registers::ReadFireflyRXReset(std::optional<uint32_t> val)
    2247              : {
    2248            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2249            0 :         return dataSet[1];
    2250              : }
    2251              : 
    2252            0 : bool CFOLib::CFO_Registers::ReadFireflyTXReset(std::optional<uint32_t> val)
    2253              : {
    2254            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FireflyCSRRegister);
    2255            0 :         return dataSet[0];
    2256              : }
    2257              : 
    2258            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatFireflyCSR()
    2259              : {
    2260            0 :         auto form = CreateFormatter(CFO_Register_FireflyCSRRegister);
    2261            0 :         form.description = "Firefly CSR Register";
    2262            0 :         form.vals.push_back("      ([Present, Interrupt, Select, Reset])");
    2263            0 :         form.vals.push_back(std::string("TX/RX: [") +
    2264            0 :                                                 (ReadFireflyTXRXPresent(form.value) ? "x" : " ") +
    2265            0 :                                                 (ReadFireflyTXRXInterrupt(form.value) ? "x" : " ") +
    2266            0 :                                                 (ReadFireflyTXRXSelect(form.value) ? "x" : " ") +
    2267            0 :                                                 (ReadFireflyTXRXReset(form.value) ? "x" : " ") + "]");
    2268            0 :         form.vals.push_back(std::string("RX:    [") +
    2269            0 :                                                 (ReadFireflyRXPresent(form.value) ? "x" : " ") +
    2270            0 :                                                 (ReadFireflyRXInterrupt(form.value) ? "x" : " ") +
    2271            0 :                                                 (ReadFireflyRXSelect(form.value) ? "x" : " ") +
    2272            0 :                                                 (ReadFireflyRXReset(form.value) ? "x" : " ") + "]");
    2273            0 :         form.vals.push_back(std::string("TX:    [") +
    2274            0 :                                                 (ReadFireflyTXPresent(form.value) ? "x" : " ") +
    2275            0 :                                                 (ReadFireflyTXInterrupt(form.value) ? "x" : " ") +
    2276            0 :                                                 (ReadFireflyTXSelect(form.value) ? "x" : " ") +
    2277            0 :                                                 (ReadFireflyTXReset(form.value) ? "x" : " ") + "]");
    2278              : 
    2279            0 :         return form;
    2280            0 : }
    2281              : 
    2282              : // SERDES PRBS Control Registers
    2283            0 : bool CFOLib::CFO_Registers::ReadSERDESPRBSErrorFlag(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2284              : {
    2285              :         CFO_Register reg;
    2286            0 :         switch (link)
    2287              :         {
    2288            0 :                 case CFO_Link_0:
    2289            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2290            0 :                         break;
    2291            0 :                 case CFO_Link_1:
    2292            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2293            0 :                         break;
    2294            0 :                 case CFO_Link_2:
    2295            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2296            0 :                         break;
    2297            0 :                 case CFO_Link_3:
    2298            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2299            0 :                         break;
    2300            0 :                 case CFO_Link_4:
    2301            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2302            0 :                         break;
    2303            0 :                 case CFO_Link_5:
    2304            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2305            0 :                         break;
    2306            0 :                 case CFO_Link_6:
    2307            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2308            0 :                         break;
    2309            0 :                 case CFO_Link_7:
    2310            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2311            0 :                         break;
    2312            0 :                 default: {
    2313            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2314            0 :                         __SS_THROW__;
    2315            0 :                 }
    2316              :         }
    2317              : 
    2318            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(reg);
    2319            0 :         return dataSet[31];
    2320              : }
    2321              : 
    2322            0 : uint8_t CFOLib::CFO_Registers::ReadSERDESTXPRBSSEL(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2323              : {
    2324              :         CFO_Register reg;
    2325            0 :         switch (link)
    2326              :         {
    2327            0 :                 case CFO_Link_0:
    2328            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2329            0 :                         break;
    2330            0 :                 case CFO_Link_1:
    2331            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2332            0 :                         break;
    2333            0 :                 case CFO_Link_2:
    2334            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2335            0 :                         break;
    2336            0 :                 case CFO_Link_3:
    2337            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2338            0 :                         break;
    2339            0 :                 case CFO_Link_4:
    2340            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2341            0 :                         break;
    2342            0 :                 case CFO_Link_5:
    2343            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2344            0 :                         break;
    2345            0 :                 case CFO_Link_6:
    2346            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2347            0 :                         break;
    2348            0 :                 case CFO_Link_7:
    2349            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2350            0 :                         break;
    2351            0 :                 default: {
    2352            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2353            0 :                         __SS_THROW__;
    2354            0 :                 }
    2355              :         }
    2356            0 :         auto data = val.has_value() ? *val : ReadRegister_(reg);
    2357            0 :         return (data >> 12) & 0xF;
    2358              : }
    2359              : 
    2360            0 : void CFOLib::CFO_Registers::SetSERDESTXPRBSSEL(const CFO_Link_ID& link, uint8_t byte)
    2361              : {
    2362              :         CFO_Register reg;
    2363            0 :         switch (link)
    2364              :         {
    2365            0 :                 case CFO_Link_0:
    2366            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2367            0 :                         break;
    2368            0 :                 case CFO_Link_1:
    2369            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2370            0 :                         break;
    2371            0 :                 case CFO_Link_2:
    2372            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2373            0 :                         break;
    2374            0 :                 case CFO_Link_3:
    2375            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2376            0 :                         break;
    2377            0 :                 case CFO_Link_4:
    2378            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2379            0 :                         break;
    2380            0 :                 case CFO_Link_5:
    2381            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2382            0 :                         break;
    2383            0 :                 case CFO_Link_6:
    2384            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2385            0 :                         break;
    2386            0 :                 case CFO_Link_7:
    2387            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2388            0 :                         break;
    2389            0 :                 default: {
    2390            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2391            0 :                         __SS_THROW__;
    2392            0 :                 }
    2393              :         }
    2394            0 :         WriteRegister_(byte, reg);
    2395            0 : }
    2396              : 
    2397            0 : uint8_t CFOLib::CFO_Registers::ReadSERDESRXPRBSSEL(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2398              : {
    2399              :         CFO_Register reg;
    2400            0 :         switch (link)
    2401              :         {
    2402            0 :                 case CFO_Link_0:
    2403            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2404            0 :                         break;
    2405            0 :                 case CFO_Link_1:
    2406            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2407            0 :                         break;
    2408            0 :                 case CFO_Link_2:
    2409            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2410            0 :                         break;
    2411            0 :                 case CFO_Link_3:
    2412            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2413            0 :                         break;
    2414            0 :                 case CFO_Link_4:
    2415            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2416            0 :                         break;
    2417            0 :                 case CFO_Link_5:
    2418            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2419            0 :                         break;
    2420            0 :                 case CFO_Link_6:
    2421            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2422            0 :                         break;
    2423            0 :                 case CFO_Link_7:
    2424            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2425            0 :                         break;
    2426            0 :                 default: {
    2427            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2428            0 :                         __SS_THROW__;
    2429            0 :                 }
    2430              :         }
    2431            0 :         auto data = val.has_value() ? *val : ReadRegister_(reg);
    2432            0 :         return (data >> 8) & 0xF;
    2433              : }
    2434              : 
    2435            0 : void CFOLib::CFO_Registers::SetSERDESRXPRBSSEL(const CFO_Link_ID& link, uint8_t byte)
    2436              : {
    2437              :         CFO_Register reg;
    2438            0 :         switch (link)
    2439              :         {
    2440            0 :                 case CFO_Link_0:
    2441            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2442            0 :                         break;
    2443            0 :                 case CFO_Link_1:
    2444            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2445            0 :                         break;
    2446            0 :                 case CFO_Link_2:
    2447            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2448            0 :                         break;
    2449            0 :                 case CFO_Link_3:
    2450            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2451            0 :                         break;
    2452            0 :                 case CFO_Link_4:
    2453            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2454            0 :                         break;
    2455            0 :                 case CFO_Link_5:
    2456            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2457            0 :                         break;
    2458            0 :                 case CFO_Link_6:
    2459            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2460            0 :                         break;
    2461            0 :                 case CFO_Link_7:
    2462            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2463            0 :                         break;
    2464            0 :                 default: {
    2465            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2466            0 :                         __SS_THROW__;
    2467            0 :                 }
    2468              :         }
    2469            0 :         WriteRegister_(byte, reg);
    2470            0 : }
    2471              : 
    2472            0 : bool CFOLib::CFO_Registers::ReadSERDESTXPRBSForceError(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2473              : {
    2474              :         CFO_Register reg;
    2475            0 :         switch (link)
    2476              :         {
    2477            0 :                 case CFO_Link_0:
    2478            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2479            0 :                         break;
    2480            0 :                 case CFO_Link_1:
    2481            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2482            0 :                         break;
    2483            0 :                 case CFO_Link_2:
    2484            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2485            0 :                         break;
    2486            0 :                 case CFO_Link_3:
    2487            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2488            0 :                         break;
    2489            0 :                 case CFO_Link_4:
    2490            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2491            0 :                         break;
    2492            0 :                 case CFO_Link_5:
    2493            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2494            0 :                         break;
    2495            0 :                 case CFO_Link_6:
    2496            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2497            0 :                         break;
    2498            0 :                 case CFO_Link_7:
    2499            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2500            0 :                         break;
    2501            0 :                 default: {
    2502            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2503            0 :                         __SS_THROW__;
    2504            0 :                 }
    2505              :         }
    2506            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(reg);
    2507            0 :         return dataSet[1];
    2508              : }
    2509              : 
    2510            0 : void CFOLib::CFO_Registers::SetSERDESTXPRBSForceError(const CFO_Link_ID& link, bool flag)
    2511              : {
    2512              :         CFO_Register reg;
    2513            0 :         switch (link)
    2514              :         {
    2515            0 :                 case CFO_Link_0:
    2516            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2517            0 :                         break;
    2518            0 :                 case CFO_Link_1:
    2519            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2520            0 :                         break;
    2521            0 :                 case CFO_Link_2:
    2522            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2523            0 :                         break;
    2524            0 :                 case CFO_Link_3:
    2525            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2526            0 :                         break;
    2527            0 :                 case CFO_Link_4:
    2528            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2529            0 :                         break;
    2530            0 :                 case CFO_Link_5:
    2531            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2532            0 :                         break;
    2533            0 :                 case CFO_Link_6:
    2534            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2535            0 :                         break;
    2536            0 :                 case CFO_Link_7:
    2537            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2538            0 :                         break;
    2539            0 :                 default: {
    2540            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2541            0 :                         __SS_THROW__;
    2542            0 :                 }
    2543              :         }
    2544            0 :         std::bitset<32> dataSet = ReadRegister_(reg);
    2545            0 :         dataSet[1] = flag;
    2546            0 :         WriteRegister_(dataSet.to_ulong(), reg);
    2547            0 : }
    2548              : 
    2549            0 : void CFOLib::CFO_Registers::ToggleSERDESTXPRBSForceError(const CFO_Link_ID& link)
    2550              : {
    2551              :         CFO_Register reg;
    2552            0 :         switch (link)
    2553              :         {
    2554            0 :                 case CFO_Link_0:
    2555            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2556            0 :                         break;
    2557            0 :                 case CFO_Link_1:
    2558            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2559            0 :                         break;
    2560            0 :                 case CFO_Link_2:
    2561            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2562            0 :                         break;
    2563            0 :                 case CFO_Link_3:
    2564            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2565            0 :                         break;
    2566            0 :                 case CFO_Link_4:
    2567            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2568            0 :                         break;
    2569            0 :                 case CFO_Link_5:
    2570            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2571            0 :                         break;
    2572            0 :                 case CFO_Link_6:
    2573            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2574            0 :                         break;
    2575            0 :                 case CFO_Link_7:
    2576            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2577            0 :                         break;
    2578            0 :                 default: {
    2579            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2580            0 :                         __SS_THROW__;
    2581            0 :                 }
    2582              :         }
    2583            0 :         std::bitset<32> dataSet = ReadRegister_(reg);
    2584            0 :         dataSet[1] = !dataSet[1];
    2585            0 :         WriteRegister_(dataSet.to_ulong(), reg);
    2586            0 : }
    2587              : 
    2588            0 : bool CFOLib::CFO_Registers::ReadSERDESRXPRBSCountReset(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2589              : {
    2590              :         CFO_Register reg;
    2591            0 :         switch (link)
    2592              :         {
    2593            0 :                 case CFO_Link_0:
    2594            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2595            0 :                         break;
    2596            0 :                 case CFO_Link_1:
    2597            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2598            0 :                         break;
    2599            0 :                 case CFO_Link_2:
    2600            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2601            0 :                         break;
    2602            0 :                 case CFO_Link_3:
    2603            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2604            0 :                         break;
    2605            0 :                 case CFO_Link_4:
    2606            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2607            0 :                         break;
    2608            0 :                 case CFO_Link_5:
    2609            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2610            0 :                         break;
    2611            0 :                 case CFO_Link_6:
    2612            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2613            0 :                         break;
    2614            0 :                 case CFO_Link_7:
    2615            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2616            0 :                         break;
    2617            0 :                 default: {
    2618            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    2619            0 :                         __SS_THROW__;
    2620            0 :                 }
    2621              :         }
    2622            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(reg);
    2623            0 :         return dataSet[0];
    2624              : }
    2625              : 
    2626            0 : void CFOLib::CFO_Registers::SetSERDESRXPRBSCountReset(const CFO_Link_ID& link, bool flag)
    2627              : {
    2628              :         CFO_Register reg;
    2629            0 :         switch (link)
    2630              :         {
    2631            0 :                 case CFO_Link_0:
    2632            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2633            0 :                         break;
    2634            0 :                 case CFO_Link_1:
    2635            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2636            0 :                         break;
    2637            0 :                 case CFO_Link_2:
    2638            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2639            0 :                         break;
    2640            0 :                 case CFO_Link_3:
    2641            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2642            0 :                         break;
    2643            0 :                 case CFO_Link_4:
    2644            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2645            0 :                         break;
    2646            0 :                 case CFO_Link_5:
    2647            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2648            0 :                         break;
    2649            0 :                 case CFO_Link_6:
    2650            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2651            0 :                         break;
    2652            0 :                 case CFO_Link_7:
    2653            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2654            0 :                         break;
    2655            0 :                 default:
    2656            0 :                         return;
    2657              :         }
    2658            0 :         std::bitset<32> dataSet = ReadRegister_(reg);
    2659            0 :         dataSet[0] = flag;
    2660            0 :         WriteRegister_(dataSet.to_ulong(), reg);
    2661              : }
    2662              : 
    2663            0 : void CFOLib::CFO_Registers::ToggleSERDESRXPRBSCountReset(const CFO_Link_ID& link)
    2664              : {
    2665              :         CFO_Register reg;
    2666            0 :         switch (link)
    2667              :         {
    2668            0 :                 case CFO_Link_0:
    2669            0 :                         reg = CFO_Register_SERDESPRBSControlLink0;
    2670            0 :                         break;
    2671            0 :                 case CFO_Link_1:
    2672            0 :                         reg = CFO_Register_SERDESPRBSControlLink1;
    2673            0 :                         break;
    2674            0 :                 case CFO_Link_2:
    2675            0 :                         reg = CFO_Register_SERDESPRBSControlLink2;
    2676            0 :                         break;
    2677            0 :                 case CFO_Link_3:
    2678            0 :                         reg = CFO_Register_SERDESPRBSControlLink3;
    2679            0 :                         break;
    2680            0 :                 case CFO_Link_4:
    2681            0 :                         reg = CFO_Register_SERDESPRBSControlLink4;
    2682            0 :                         break;
    2683            0 :                 case CFO_Link_5:
    2684            0 :                         reg = CFO_Register_SERDESPRBSControlLink5;
    2685            0 :                         break;
    2686            0 :                 case CFO_Link_6:
    2687            0 :                         reg = CFO_Register_SERDESPRBSControlLink6;
    2688            0 :                         break;
    2689            0 :                 case CFO_Link_7:
    2690            0 :                         reg = CFO_Register_SERDESPRBSControlLink7;
    2691            0 :                         break;
    2692            0 :                 default:
    2693            0 :                         return;
    2694              :         }
    2695            0 :         std::bitset<32> dataSet = ReadRegister_(reg);
    2696            0 :         dataSet[0] = !dataSet[0];
    2697            0 :         WriteRegister_(dataSet.to_ulong(), reg);
    2698              : }
    2699              : 
    2700            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink0()
    2701              : {
    2702            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink0);
    2703            0 :         form.description = "SERDES PRBS Control Link 0";
    2704            0 :         form.vals.push_back("");  // translation
    2705            0 :         std::ostringstream o;
    2706            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_0, form.value);
    2707            0 :         form.vals.push_back(o.str());
    2708            0 :         o.flush();
    2709            0 :         o.str("");
    2710            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_0, form.value));
    2711            0 :         form.vals.push_back(o.str());
    2712            0 :         o.flush();
    2713            0 :         o.str("");
    2714            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_0, form.value));
    2715            0 :         form.vals.push_back(o.str());
    2716            0 :         o.flush();
    2717            0 :         o.str("");
    2718            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_0, form.value);
    2719            0 :         form.vals.push_back(o.str());
    2720            0 :         o.flush();
    2721            0 :         o.str("");
    2722            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_0, form.value);
    2723            0 :         form.vals.push_back(o.str());
    2724            0 :         o.flush();
    2725              : 
    2726            0 :         return form;
    2727            0 : }
    2728              : 
    2729            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink1()
    2730              : {
    2731            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink1);
    2732            0 :         form.description = "SERDES PRBS Control Link 1";
    2733            0 :         form.vals.push_back("");  // translation
    2734            0 :         std::ostringstream o;
    2735            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_1, form.value);
    2736            0 :         form.vals.push_back(o.str());
    2737            0 :         o.flush();
    2738            0 :         o.str("");
    2739            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_1, form.value));
    2740            0 :         form.vals.push_back(o.str());
    2741            0 :         o.flush();
    2742            0 :         o.str("");
    2743            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_1, form.value));
    2744            0 :         form.vals.push_back(o.str());
    2745            0 :         o.flush();
    2746            0 :         o.str("");
    2747            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_1, form.value);
    2748            0 :         form.vals.push_back(o.str());
    2749            0 :         o.flush();
    2750            0 :         o.str("");
    2751            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_1, form.value);
    2752            0 :         form.vals.push_back(o.str());
    2753            0 :         o.flush();
    2754              : 
    2755            0 :         return form;
    2756            0 : }
    2757              : 
    2758            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink2()
    2759              : {
    2760            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink2);
    2761            0 :         form.description = "SERDES PRBS Control Link 2";
    2762            0 :         form.vals.push_back("");  // translation
    2763            0 :         std::ostringstream o;
    2764            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_2, form.value);
    2765            0 :         form.vals.push_back(o.str());
    2766            0 :         o.flush();
    2767            0 :         o.str("");
    2768            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_2, form.value));
    2769            0 :         form.vals.push_back(o.str());
    2770            0 :         o.flush();
    2771            0 :         o.str("");
    2772            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_2, form.value));
    2773            0 :         form.vals.push_back(o.str());
    2774            0 :         o.flush();
    2775            0 :         o.str("");
    2776            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_2, form.value);
    2777            0 :         form.vals.push_back(o.str());
    2778            0 :         o.flush();
    2779            0 :         o.str("");
    2780            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_2, form.value);
    2781            0 :         form.vals.push_back(o.str());
    2782            0 :         o.flush();
    2783              : 
    2784            0 :         return form;
    2785            0 : }
    2786              : 
    2787            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink3()
    2788              : {
    2789            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink3);
    2790            0 :         form.description = "SERDES PRBS Control Link 3";
    2791            0 :         form.vals.push_back("");  // translation
    2792            0 :         std::ostringstream o;
    2793            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_3, form.value);
    2794            0 :         form.vals.push_back(o.str());
    2795            0 :         o.flush();
    2796            0 :         o.str("");
    2797            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_3, form.value));
    2798            0 :         form.vals.push_back(o.str());
    2799            0 :         o.flush();
    2800            0 :         o.str("");
    2801            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_3, form.value));
    2802            0 :         form.vals.push_back(o.str());
    2803            0 :         o.flush();
    2804            0 :         o.str("");
    2805            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_3, form.value);
    2806            0 :         form.vals.push_back(o.str());
    2807            0 :         o.flush();
    2808            0 :         o.str("");
    2809            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_3, form.value);
    2810            0 :         form.vals.push_back(o.str());
    2811            0 :         o.flush();
    2812              : 
    2813            0 :         return form;
    2814            0 : }
    2815              : 
    2816            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink4()
    2817              : {
    2818            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink4);
    2819            0 :         form.description = "SERDES PRBS Control Link 4";
    2820            0 :         form.vals.push_back("");  // translation
    2821            0 :         std::ostringstream o;
    2822            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_4, form.value);
    2823            0 :         form.vals.push_back(o.str());
    2824            0 :         o.flush();
    2825            0 :         o.str("");
    2826            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_4, form.value));
    2827            0 :         form.vals.push_back(o.str());
    2828            0 :         o.flush();
    2829            0 :         o.str("");
    2830            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_4, form.value));
    2831            0 :         form.vals.push_back(o.str());
    2832            0 :         o.flush();
    2833            0 :         o.str("");
    2834            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_4, form.value);
    2835            0 :         form.vals.push_back(o.str());
    2836            0 :         o.flush();
    2837            0 :         o.str("");
    2838            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_4, form.value);
    2839            0 :         form.vals.push_back(o.str());
    2840            0 :         o.flush();
    2841              : 
    2842            0 :         return form;
    2843            0 : }
    2844              : 
    2845            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink5()
    2846              : {
    2847            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink5);
    2848            0 :         form.description = "SERDES PRBS Control Link 5";
    2849            0 :         form.vals.push_back("");  // translation
    2850            0 :         std::ostringstream o;
    2851            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_5, form.value);
    2852            0 :         form.vals.push_back(o.str());
    2853            0 :         o.flush();
    2854            0 :         o.str("");
    2855            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_5, form.value));
    2856            0 :         form.vals.push_back(o.str());
    2857            0 :         o.flush();
    2858            0 :         o.str("");
    2859            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_5, form.value));
    2860            0 :         form.vals.push_back(o.str());
    2861            0 :         o.flush();
    2862            0 :         o.str("");
    2863            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_5, form.value);
    2864            0 :         form.vals.push_back(o.str());
    2865            0 :         o.flush();
    2866            0 :         o.str("");
    2867            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_5, form.value);
    2868            0 :         form.vals.push_back(o.str());
    2869            0 :         o.flush();
    2870              : 
    2871            0 :         return form;
    2872            0 : }
    2873              : 
    2874            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink6()
    2875              : {
    2876            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink6);
    2877            0 :         form.description = "SERDES PRBS Control Link 6";
    2878            0 :         form.vals.push_back("");  // translation
    2879            0 :         std::ostringstream o;
    2880            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_6, form.value);
    2881            0 :         form.vals.push_back(o.str());
    2882            0 :         o.flush();
    2883            0 :         o.str("");
    2884            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_6, form.value));
    2885            0 :         form.vals.push_back(o.str());
    2886            0 :         o.flush();
    2887            0 :         o.str("");
    2888            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_6, form.value));
    2889            0 :         form.vals.push_back(o.str());
    2890            0 :         o.flush();
    2891            0 :         o.str("");
    2892            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_6, form.value);
    2893            0 :         form.vals.push_back(o.str());
    2894            0 :         o.flush();
    2895            0 :         o.str("");
    2896            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_6, form.value);
    2897            0 :         form.vals.push_back(o.str());
    2898            0 :         o.flush();
    2899              : 
    2900            0 :         return form;
    2901            0 : }
    2902              : 
    2903            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatSERDESPRBSControlLink7()
    2904              : {
    2905            0 :         auto form = CreateFormatter(CFO_Register_SERDESPRBSControlLink7);
    2906            0 :         form.description = "SERDES PRBS Control Link 7";
    2907            0 :         form.vals.push_back("");  // translation
    2908            0 :         std::ostringstream o;
    2909            0 :         o << "RX PRBS Error:              " << std::boolalpha << ReadSERDESPRBSErrorFlag(CFO_Link_7, form.value);
    2910            0 :         form.vals.push_back(o.str());
    2911            0 :         o.flush();
    2912            0 :         o.str("");
    2913            0 :         o << "TX PRBS Select:             " << std::to_string(ReadSERDESTXPRBSSEL(CFO_Link_7, form.value));
    2914            0 :         form.vals.push_back(o.str());
    2915            0 :         o.flush();
    2916            0 :         o.str("");
    2917            0 :         o << "RX PRBS Select:             " << std::to_string(ReadSERDESRXPRBSSEL(CFO_Link_7, form.value));
    2918            0 :         form.vals.push_back(o.str());
    2919            0 :         o.flush();
    2920            0 :         o.str("");
    2921            0 :         o << "TX PRBS Enable Force Error: " << std::boolalpha << ReadSERDESTXPRBSForceError(CFO_Link_7, form.value);
    2922            0 :         form.vals.push_back(o.str());
    2923            0 :         o.flush();
    2924            0 :         o.str("");
    2925            0 :         o << "RX PRBS Count Reset:        " << std::boolalpha << ReadSERDESRXPRBSCountReset(CFO_Link_7, form.value);
    2926            0 :         form.vals.push_back(o.str());
    2927            0 :         o.flush();
    2928              : 
    2929            0 :         return form;
    2930            0 : }
    2931              : 
    2932            0 : uint32_t CFOLib::CFO_Registers::ReadCableDelayMeasureExponentialCount(std::optional<uint32_t> val)
    2933              : {
    2934            0 :         uint32_t readVal = val.has_value() ? *val : ReadRegister_(CFO_Register_CableDelayControlStatus);
    2935            0 :         return (readVal >> 16) & 0xF;  // return 4-bit nibble at bit-16
    2936              : }  // end ReadCableDelayMeasureExponentialCount()
    2937              : 
    2938            0 : void CFOLib::CFO_Registers::SetCableDelayMeasureExponentialCount(const uint32_t exponent)
    2939              : {
    2940            0 :         uint32_t val = ReadRegister_(CFO_Register_CableDelayControlStatus);
    2941            0 :         val &= ~(0x0F << 16);           // mask off
    2942            0 :         val |= (exponent & 0xF) << 16;  // insert 4-bit nibble at bit-16
    2943            0 :         WriteRegister_(val, CFO_Register_CableDelayControlStatus);
    2944            0 : }  // end SetCableDelayMeasureExponentialCount()
    2945              : 
    2946            0 : uint32_t CFOLib::CFO_Registers::ReadCableDelayMeasurement(const CFO_Link_ID link, const uint8_t roc, bool& done)
    2947              : {
    2948            0 :         CFOandDTC_Register calcReg = CFO_Register_CableDelayValue_offset;
    2949            0 :         calcReg += 0x100 * roc;
    2950            0 :         calcReg += 0x4 * link;
    2951            0 :         __COUTT__ << "Delay Register 0x" << std::hex << calcReg << __E__;
    2952            0 :         uint32_t readVal = ReadRegister_(calcReg);
    2953            0 :         done = (readVal >> 31) & 1;
    2954            0 :         return readVal & (~(1 << 31));  // return 4-bit nibble at bit-16
    2955              : }  // end ReadCableDelayMeasureExponentialCount()
    2956              : 
    2957              : // void CFOLib::CFO_Registers::SetCableDelayValue(const CFO_Link_ID& link, const uint32_t delay)
    2958              : // {
    2959              : //      CFO_Register reg;
    2960              : //      switch (link)
    2961              : //      {
    2962              : //              case CFO_Link_0:
    2963              : //                      reg = CFO_Register_CableDelayValueLink0;
    2964              : //                      break;
    2965              : //              case CFO_Link_1:
    2966              : //                      reg = CFO_Register_CableDelayValueLink1;
    2967              : //                      break;
    2968              : //              case CFO_Link_2:
    2969              : //                      reg = CFO_Register_CableDelayValueLink2;
    2970              : //                      break;
    2971              : //              case CFO_Link_3:
    2972              : //                      reg = CFO_Register_CableDelayValueLink3;
    2973              : //                      break;
    2974              : //              case CFO_Link_4:
    2975              : //                      reg = CFO_Register_CableDelayValueLink4;
    2976              : //                      break;
    2977              : //              case CFO_Link_5:
    2978              : //                      reg = CFO_Register_CableDelayValueLink5;
    2979              : //                      break;
    2980              : //              case CFO_Link_6:
    2981              : //                      reg = CFO_Register_CableDelayValueLink6;
    2982              : //                      break;
    2983              : //              case CFO_Link_7:
    2984              : //                      reg = CFO_Register_CableDelayValueLink7;
    2985              : //                      break;
    2986              : //              default:
    2987              : //                      return;
    2988              : //      }
    2989              : //      WriteRegister_(delay, reg);
    2990              : // }
    2991              : 
    2992              : // uint32_t CFOLib::CFO_Registers::ReadCableDelayValue(const CFO_Link_ID& link, std::optional<uint32_t> val)
    2993              : // {
    2994              : //      switch (link)
    2995              : //      {
    2996              : //              case CFO_Link_0:
    2997              : //                      return val.has_value()?*val:ReadRegister_(CFO_Register_CableDelayValueLink0);
    2998              : //              case CFO_Link_1:
    2999              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink1);
    3000              : //              case CFO_Link_2:
    3001              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink2);
    3002              : //              case CFO_Link_3:
    3003              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink3);
    3004              : //              case CFO_Link_4:
    3005              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink4);
    3006              : //              case CFO_Link_5:
    3007              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink5);
    3008              : //              case CFO_Link_6:
    3009              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink6);
    3010              : //              case CFO_Link_7:
    3011              : //                      return ReadRegister_(CFO_Register_CableDelayValueLink7);
    3012              : //              default:
    3013              : //                      return -1;
    3014              : //      }
    3015              : // }
    3016              : 
    3017              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink0()
    3018              : // {
    3019              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink0);
    3020              : //      form.description = "Cable Delay Value Link 0";
    3021              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_0)));
    3022              : //      return form;
    3023              : // }
    3024              : 
    3025              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink1()
    3026              : // {
    3027              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink1);
    3028              : //      form.description = "Cable Delay Value Link 1";
    3029              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_1)));
    3030              : //      return form;
    3031              : // }
    3032              : 
    3033              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink2()
    3034              : // {
    3035              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink2);
    3036              : //      form.description = "Cable Delay Value Link 2";
    3037              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_2)));
    3038              : //      return form;
    3039              : // }
    3040              : 
    3041              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink3()
    3042              : // {
    3043              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink3);
    3044              : //      form.description = "Cable Delay Value Link 3";
    3045              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_3)));
    3046              : //      return form;
    3047              : // }
    3048              : 
    3049              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink4()
    3050              : // {
    3051              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink4);
    3052              : //      form.description = "Cable Delay Value Link 4";
    3053              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_4)));
    3054              : //      return form;
    3055              : // }
    3056              : 
    3057              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink5()
    3058              : // {
    3059              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink5);
    3060              : //      form.description = "Cable Delay Value Link 5";
    3061              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_5)));
    3062              : //      return form;
    3063              : // }
    3064              : 
    3065              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink6()
    3066              : // {
    3067              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink6);
    3068              : //      form.description = "Cable Delay Value Link 6";
    3069              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_6)));
    3070              : //      return form;
    3071              : // }
    3072              : 
    3073              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayValueLink7()
    3074              : // {
    3075              : //      auto form = CreateFormatter(CFO_Register_CableDelayValueLink7);
    3076              : //      form.description = "Cable Delay Value Link 7";
    3077              : //      form.vals.push_back(std::to_string(ReadCableDelayValue(CFO_Link_7)));
    3078              : //      return form;
    3079              : // }
    3080              : 
    3081              : // void CFOLib::CFO_Registers::ResetDelayRegister()
    3082              : // {
    3083              : //      WriteRegister_(0, CFO_Register_CableDelayControlStatus);
    3084              : // }
    3085              : 
    3086              : // bool CFOLib::CFO_Registers::ReadDelayMeasureError(const CFO_Link_ID& link, std::optional<uint32_t> val)
    3087              : // {
    3088              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(CFO_Register_CableDelayControlStatus);
    3089              : //      return dataSet[24 + link];
    3090              : // }
    3091              : 
    3092              : // bool CFOLib::CFO_Registers::ReadDelayExternalLoopbackEnable(std::optional<uint32_t> val)
    3093              : // {
    3094              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(CFO_Register_CableDelayControlStatus);
    3095              : //      return dataSet[16];
    3096              : // }
    3097              : 
    3098              : // void CFOLib::CFO_Registers::SetDelayExternalLoopbackEnable(bool value)
    3099              : // {
    3100              : //      std::bitset<32> dataSet = ReadRegister_(CFO_Register_CableDelayControlStatus);
    3101              : //      dataSet[16] = value;
    3102              : //      WriteRegister_(dataSet.to_ulong(), CFO_Register_CableDelayControlStatus);
    3103              : // }
    3104              : 
    3105              : // void CFOLib::CFO_Registers::EnableDelayMeasureMode(const CFO_Link_ID& link)
    3106              : // {
    3107              : //      std::bitset<32> dataSet = ReadRegister_(CFO_Register_CableDelayControlStatus);
    3108              : //      dataSet[8 + link] = 1;
    3109              : //      WriteRegister_(dataSet.to_ulong(), CFO_Register_CableDelayControlStatus);
    3110              : // }
    3111              : 
    3112              : // void CFOLib::CFO_Registers::DisableDelayMeasureMode(const CFO_Link_ID& link)
    3113              : // {
    3114              : //      std::bitset<32> dataSet = ReadRegister_(CFO_Register_CableDelayControlStatus);
    3115              : //      dataSet[8 + link] = 0;
    3116              : //      WriteRegister_(dataSet.to_ulong(), CFO_Register_CableDelayControlStatus);
    3117              : // }
    3118              : 
    3119              : // bool CFOLib::CFO_Registers::ReadDelayMeasureMode(const CFO_Link_ID& link, std::optional<uint32_t> val)
    3120              : // {
    3121              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(CFO_Register_CableDelayControlStatus);
    3122              : //      return dataSet[8 + link];
    3123              : // }
    3124              : 
    3125              : // void CFOLib::CFO_Registers::EnableDelayMeasureNow(const CFO_Link_ID& link)
    3126              : // {
    3127              : //      std::bitset<32> dataSet = ReadRegister_(CFO_Register_CableDelayControlStatus);
    3128              : //      dataSet[link] = 1;
    3129              : //      WriteRegister_(dataSet.to_ulong(), CFO_Register_CableDelayControlStatus);
    3130              : // }
    3131              : 
    3132              : // void CFOLib::CFO_Registers::DisableDelayMeasureNow(const CFO_Link_ID& link)
    3133              : // {
    3134              : //      std::bitset<32> dataSet = ReadRegister_(CFO_Register_CableDelayControlStatus);
    3135              : //      dataSet[link] = 0;
    3136              : //      WriteRegister_(dataSet.to_ulong(), CFO_Register_CableDelayControlStatus);
    3137              : // }
    3138              : 
    3139              : // bool CFOLib::CFO_Registers::ReadDelayMeasureNow(const CFO_Link_ID& link, std::optional<uint32_t> val)
    3140              : // {
    3141              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(CFO_Register_CableDelayControlStatus);
    3142              : //      return dataSet[link];
    3143              : // }
    3144              : 
    3145              : // DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatCableDelayControl()
    3146              : // {
    3147              : //      auto form = CreateFormatter(CFO_Register_CableDelayControlStatus);
    3148              : //      form.description = "Cabel Delay Control and Status";
    3149              : //      form.vals.push_back("[ x = 1 (hi) ]"); //translation
    3150              : //      form.vals.push_back(std::string("Delay External Loopback Enable: [") +
    3151              : //                                              (ReadDelayExternalLoopbackEnable(form.value) ? "x" : " ") + std::string("]"));
    3152              : //      form.vals.push_back(std::string("Delay Measure Flags:           ([Error, Enabled, Now])"));
    3153              : //      for (auto r : CFO_Links)
    3154              : //              form.vals.push_back(std::string("Link ") + std::to_string(r) + ":                         [" +
    3155              : //                                                      (ReadDelayMeasureError(r, form.value) ? "x" : " ") + "," +
    3156              : //                                                      (ReadDelayMeasureMode(r, form.value) ? "x" : " ") + "," +
    3157              : //                                                      (ReadDelayMeasureNow(r, form.value) ? "x" : " ") + "]");
    3158              : //      return form;
    3159              : // }
    3160              : 
    3161              : // FPGA PROM Program Status Register
    3162            0 : bool CFOLib::CFO_Registers::ReadFPGAPROMProgramFIFOFull(std::optional<uint32_t> val)
    3163              : {
    3164            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FPGAPROMProgramStatus);
    3165            0 :         return dataSet[1];
    3166              : }
    3167              : 
    3168            0 : bool CFOLib::CFO_Registers::ReadFPGAPROMReady(std::optional<uint32_t> val)
    3169              : {
    3170            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FPGAPROMProgramStatus);
    3171            0 :         return dataSet[0];
    3172              : }
    3173              : 
    3174            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatFPGAPROMProgramStatus()
    3175              : {
    3176            0 :         auto form = CreateFormatter(CFO_Register_FPGAPROMProgramStatus);
    3177            0 :         form.description = "FPGA PROM Program Status";
    3178            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
    3179            0 :         form.vals.push_back(std::string("FPGA PROM Program FIFO Full: [") + (ReadFPGAPROMProgramFIFOFull(form.value) ? "x" : " ") +
    3180              :                                                 "]");
    3181            0 :         form.vals.push_back(std::string("FPGA PROM Ready:             [") + (ReadFPGAPROMReady(form.value) ? "x" : " ") + "]");
    3182            0 :         return form;
    3183            0 : }
    3184              : 
    3185              : // FPGA Core Access Register
    3186            0 : void CFOLib::CFO_Registers::ReloadFPGAFirmware()
    3187              : {
    3188            0 :         WriteRegister_(0xFFFFFFFF, CFO_Register_FPGACoreAccess);
    3189            0 :         while (ReadFPGACoreAccessFIFOFull())
    3190              :         {
    3191            0 :                 usleep(10);
    3192              :         }
    3193            0 :         WriteRegister_(0xAA995566, CFO_Register_FPGACoreAccess);
    3194            0 :         while (ReadFPGACoreAccessFIFOFull())
    3195              :         {
    3196            0 :                 usleep(10);
    3197              :         }
    3198            0 :         WriteRegister_(0x20000000, CFO_Register_FPGACoreAccess);
    3199            0 :         while (ReadFPGACoreAccessFIFOFull())
    3200              :         {
    3201            0 :                 usleep(10);
    3202              :         }
    3203            0 :         WriteRegister_(0x30020001, CFO_Register_FPGACoreAccess);
    3204            0 :         while (ReadFPGACoreAccessFIFOFull())
    3205              :         {
    3206            0 :                 usleep(10);
    3207              :         }
    3208            0 :         WriteRegister_(0x00000000, CFO_Register_FPGACoreAccess);
    3209            0 :         while (ReadFPGACoreAccessFIFOFull())
    3210              :         {
    3211            0 :                 usleep(10);
    3212              :         }
    3213            0 :         WriteRegister_(0x30008001, CFO_Register_FPGACoreAccess);
    3214            0 :         while (ReadFPGACoreAccessFIFOFull())
    3215              :         {
    3216            0 :                 usleep(10);
    3217              :         }
    3218            0 :         WriteRegister_(0x0000000F, CFO_Register_FPGACoreAccess);
    3219            0 :         while (ReadFPGACoreAccessFIFOFull())
    3220              :         {
    3221            0 :                 usleep(10);
    3222              :         }
    3223            0 :         WriteRegister_(0x20000000, CFO_Register_FPGACoreAccess);
    3224            0 : }
    3225              : 
    3226            0 : bool CFOLib::CFO_Registers::ReadFPGACoreAccessFIFOFull(std::optional<uint32_t> val)
    3227              : {
    3228            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FPGACoreAccess);
    3229            0 :         return dataSet[1];
    3230              : }
    3231              : 
    3232            0 : bool CFOLib::CFO_Registers::ReadFPGACoreAccessFIFOEmpty(std::optional<uint32_t> val)
    3233              : {
    3234            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFO_Register_FPGACoreAccess);
    3235            0 :         return dataSet[0];
    3236              : }
    3237              : 
    3238            0 : DTCLib::RegisterFormatter CFOLib::CFO_Registers::FormatFPGACoreAccess()
    3239              : {
    3240            0 :         auto form = CreateFormatter(CFO_Register_FPGACoreAccess);
    3241            0 :         form.description = "FPGA Core Access";
    3242            0 :         form.vals.push_back("[ x = 1 (hi) ]");  // translation
    3243            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Full:  [") + (ReadFPGACoreAccessFIFOFull(form.value) ? "x" : " ") + "]");
    3244            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Empty: [") + (ReadFPGACoreAccessFIFOEmpty(form.value) ? "x" : " ") +
    3245              :                                                 "]");
    3246              : 
    3247            0 :         return form;
    3248            0 : }
    3249              : 
    3250              : // Oscillator Programming (DDR and SERDES)
    3251            0 : bool CFOLib::CFO_Registers::SetNewOscillatorFrequency(double targetFrequency)
    3252              : {
    3253            0 :         auto currentFrequency = ReadSERDESOscillatorFrequency();
    3254            0 :         auto currentProgram = ReadSERDESOscillatorParameters();
    3255            0 :         __COUT__ << "Target Frequency: " << targetFrequency << ", Current Frequency: " << currentFrequency
    3256            0 :                          << ", Current Program: " << std::showbase << std::hex << currentProgram;
    3257              : 
    3258              :         // Check if targetFrequency is essentially the same as the current frequency...
    3259            0 :         if (fabs(currentFrequency - targetFrequency) < targetFrequency * 30 / 1000000)
    3260              :         {
    3261            0 :                 __COUT_INFO__ << "New frequency and old frequency are within 30 ppm of each other, not reprogramming!";
    3262            0 :                 return false;
    3263              :         }
    3264              : 
    3265            0 :         auto newParameters = CalculateFrequencyForProgramming_(targetFrequency, currentFrequency, currentProgram);
    3266            0 :         if (newParameters == 0)
    3267              :         {
    3268            0 :                 __COUT_WARN__ << "New program calculated as 0! Check parameters!";
    3269            0 :                 return false;
    3270              :         }
    3271            0 :         SetSERDESOscillatorParameters(newParameters);
    3272            0 :         SetSERDESOscillatorFrequency(targetFrequency);
    3273            0 :         return true;
    3274              : }
    3275              : 
    3276            0 : void CFOLib::CFO_Registers::DisableLinks()
    3277              : {
    3278            0 :         __COUT_INFO__ << "CFO disable serdes transmit and receive";
    3279            0 :         WriteRegister_(0, CFOandDTC_Register_LinkEnable);
    3280            0 : }
    3281              : 
    3282            0 : void CFOLib::CFO_Registers::DisableAllOutputs()
    3283              : {
    3284            0 :         __COUT_INFO__ << "CFO disable Event Start character output";
    3285            0 :         WriteRegister_(0, CFOandDTC_Register_Control);
    3286              : 
    3287            0 :         __COUT_INFO__ << "CFO disable serdes transmit and receive";
    3288            0 :         WriteRegister_(0, CFOandDTC_Register_LinkEnable);
    3289              : 
    3290            0 :         __COUT_INFO__ << "CFO turn off Event Windows";
    3291              :         // WriteRegister_(0,CFO_Register_EventWindowEmulatorIntervalTime);
    3292            0 :         DisableBeamOnMode(CFOLib::CFO_Link_ID::CFO_Link_ALL);
    3293            0 :         DisableBeamOffMode(CFOLib::CFO_Link_ID::CFO_Link_ALL);
    3294              : 
    3295              :         // LEGACY: register 0x9154 repurposed as RunPlanSubrunEvtLimit; no longer writing ClockMarkerIntervalCount
    3296              :         // __COUT_INFO__ << "CFO turn off 40MHz marker interval";
    3297              :         // WriteRegister_(0, CFO_Register_ClockMarkerIntervalCount);
    3298            0 : }
    3299              : 
    3300              : // Private Functions
    3301            0 : bool CFOLib::CFO_Registers::NeedToVerifyRegisterWrite_(const CFOandDTC_Register& address)
    3302              : {
    3303            0 :         switch (address)
    3304              :         {
    3305              :                 // list all registers that do no need to be verified
    3306            0 :                 case CFO_Register_RunPlan_Data:
    3307            0 :                         return false;
    3308            0 :                 default:;
    3309              :         }
    3310            0 :         return true;
    3311              : }  // end NeedToVerifyRegisterWrite_()
    3312              : 
    3313            0 : void CFOLib::CFO_Registers::VerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite)
    3314              : {
    3315              :         // verify register readback
    3316              :         if (1)
    3317              :         {
    3318            0 :                 switch (address)  // handle special register checks by masking of DONT-CARE bits, or else check full 32 bits
    3319              :                 {
    3320              :                         //---------- CFO only registers
    3321            0 :                         case CFO_Register_JitterAttenuatorCSR:  // 0x9500 bit-0 is reset, input select bit-5:4, bit-8 is LOL, bit-11:9
    3322              :                                                                                                         // (input LOS).. only check input select bits
    3323            0 :                                 dataToWrite &= (3 << 4);
    3324            0 :                                 readbackValue &= (3 << 4);
    3325            0 :                                 break;
    3326              : 
    3327            0 :                         default:;  // do direct comparison of each bit
    3328              :                 }              // end readback verification address case handling
    3329              : 
    3330            0 :                 if (readbackValue != dataToWrite)
    3331              :                 {
    3332              :                         try
    3333              :                         {
    3334            0 :                                 __SS__ << "Write check mismatch - "
    3335            0 :                                            << "write value 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(dataToWrite)
    3336            0 :                                            << " to register 0x" << std::setw(4) << std::setfill('0') << std::setprecision(4) << std::hex << static_cast<uint32_t>(address) << "... read back 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(readbackValue) << std::endl
    3337            0 :                                            << std::endl
    3338            0 :                                            << "If you do not understand this error, try checking the CFO firmware version: " << ReadDesignDate() << std::endl;
    3339            0 :                                 __SS_ONLY_THROW__;
    3340            0 :                         }
    3341            0 :                         catch (const std::runtime_error& e)
    3342              :                         {
    3343            0 :                                 std::stringstream ss;
    3344            0 :                                 ss << e.what();
    3345              :                                 ss << "\n\nThe stack trace is as follows:\n"
    3346            0 :                                    << otsStyleStackTrace() << __E__;  // artdaq::debug::getStackTraceCollector().print_stacktrace() << __E__;
    3347            0 :                                 __SS_THROW__;
    3348            0 :                         }
    3349              : 
    3350              :                         // __COUT_ERR__ << ss.str();
    3351              :                         // throw DTC_IOErrorException(ss.str());
    3352              :                         // __FE_COUT_ERR__ << ss.str();
    3353              :                 }
    3354              : 
    3355              :         }  // end verify register readback
    3356            0 : }
    3357              : 
    3358            0 : int CFOLib::CFO_Registers::DecodeHighSpeedDivider_(int input)
    3359              : {
    3360            0 :         switch (input)
    3361              :         {
    3362            0 :                 case 0:
    3363            0 :                         return 4;
    3364            0 :                 case 1:
    3365            0 :                         return 5;
    3366            0 :                 case 2:
    3367            0 :                         return 6;
    3368            0 :                 case 3:
    3369            0 :                         return 7;
    3370            0 :                 case 5:
    3371            0 :                         return 9;
    3372            0 :                 case 7:
    3373            0 :                         return 11;
    3374            0 :                 default:
    3375            0 :                         return -1;
    3376              :         }
    3377              : }
    3378              : 
    3379            0 : int CFOLib::CFO_Registers::EncodeHighSpeedDivider_(int input)
    3380              : {
    3381            0 :         switch (input)
    3382              :         {
    3383            0 :                 case 4:
    3384            0 :                         return 0;
    3385            0 :                 case 5:
    3386            0 :                         return 1;
    3387            0 :                 case 6:
    3388            0 :                         return 2;
    3389            0 :                 case 7:
    3390            0 :                         return 3;
    3391            0 :                 case 9:
    3392            0 :                         return 5;
    3393            0 :                 case 11:
    3394            0 :                         return 7;
    3395            0 :                 default:
    3396            0 :                         return -1;
    3397              :         }
    3398              : }
    3399              : 
    3400            0 : int CFOLib::CFO_Registers::EncodeOutputDivider_(int input)
    3401              : {
    3402            0 :         if (input == 1) return 0;
    3403            0 :         int temp = input / 2;
    3404            0 :         return (temp * 2) - 1;
    3405              : }
    3406              : 
    3407            0 : uint64_t CFOLib::CFO_Registers::CalculateFrequencyForProgramming_(double targetFrequency, double currentFrequency,
    3408              :                                                                                                                                   uint64_t currentProgram)
    3409              : {
    3410            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: targetFrequency=" << targetFrequency << ", currentFrequency=" << currentFrequency
    3411            0 :                                                          << ", currentProgram=" << std::showbase << std::hex << static_cast<unsigned long long>(currentProgram);
    3412            0 :         auto currentHighSpeedDivider = DecodeHighSpeedDivider_((currentProgram >> 45) & 0x7);
    3413            0 :         auto currentOutputDivider = DecodeOutputDivider_((currentProgram >> 38) & 0x7F);
    3414            0 :         auto currentRFREQ = DecodeRFREQ_(currentProgram & 0x3FFFFFFFFF);
    3415            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Current HSDIV=" << currentHighSpeedDivider << ", N1=" << currentOutputDivider << ", RFREQ=" << currentRFREQ;
    3416            0 :         const auto minFreq = 4850000000;  // Hz
    3417            0 :         const auto maxFreq = 5670000000;  // Hz
    3418              : 
    3419            0 :         auto fXTAL = currentFrequency * currentHighSpeedDivider * currentOutputDivider / currentRFREQ;
    3420            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: fXTAL=" << fXTAL;
    3421              : 
    3422            0 :         std::vector<int> hsdiv_values = {11, 9, 7, 6, 5, 4};
    3423            0 :         std::vector<std::pair<int, double>> parameter_values;
    3424            0 :         for (auto hsdiv : hsdiv_values)
    3425              :         {
    3426            0 :                 auto minN = minFreq / (targetFrequency * hsdiv);
    3427            0 :                 if (minN > 128) break;
    3428              : 
    3429            0 :                 auto thisN = 2;
    3430            0 :                 if (minN < 1) thisN = 1;
    3431            0 :                 while (thisN < minN)
    3432              :                 {
    3433            0 :                         thisN += 2;
    3434              :                 }
    3435            0 :                 auto fdco_new = hsdiv * thisN * targetFrequency;
    3436            0 :                 TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Adding solution: HSDIV=" << hsdiv << ", N1=" << thisN << ", fdco_new=" << fdco_new;
    3437            0 :                 parameter_values.push_back(std::make_pair(thisN, fdco_new));
    3438              :         }
    3439              : 
    3440            0 :         auto counter = -1;
    3441            0 :         auto newHighSpeedDivider = 0;
    3442            0 :         auto newOutputDivider = 0;
    3443            0 :         auto newRFREQ = 0.0;
    3444              : 
    3445            0 :         for (auto values : parameter_values)
    3446              :         {
    3447            0 :                 ++counter;
    3448            0 :                 if (values.second > maxFreq) continue;
    3449              : 
    3450            0 :                 newHighSpeedDivider = hsdiv_values[counter];
    3451            0 :                 newOutputDivider = values.first;
    3452            0 :                 newRFREQ = values.second / fXTAL;
    3453            0 :                 break;
    3454              :         }
    3455            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: HSDIV=" << newHighSpeedDivider << ", N1=" << newOutputDivider << ", RFREQ=" << newRFREQ;
    3456              : 
    3457            0 :         if (EncodeHighSpeedDivider_(newHighSpeedDivider) == -1)
    3458              :         {
    3459            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid HSDIV " << newHighSpeedDivider << "!";
    3460            0 :                 return 0;
    3461              :         }
    3462            0 :         if (newOutputDivider > 128 || newOutputDivider < 0)
    3463              :         {
    3464            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid N1 " << newOutputDivider << "!";
    3465            0 :                 return 0;
    3466              :         }
    3467            0 :         if (newRFREQ <= 0)
    3468              :         {
    3469            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid RFREQ " << newRFREQ << "!";
    3470            0 :                 return 0;
    3471              :         }
    3472              : 
    3473            0 :         auto output = (static_cast<uint64_t>(EncodeHighSpeedDivider_(newHighSpeedDivider)) << 45) +
    3474            0 :                                   (static_cast<uint64_t>(EncodeOutputDivider_(newOutputDivider)) << 38) + EncodeRFREQ_(newRFREQ);
    3475            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: " << std::showbase << std::hex << static_cast<unsigned long long>(output);
    3476            0 :         return output;
    3477            0 : }
        

Generated by: LCOV version 2.0-1