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

Generated by: LCOV version 2.0-1