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

Generated by: LCOV version 2.0-1