LCOV - code coverage report
Current view: top level - mu2e-pcie-utils/dtcInterfaceLib - DTC_Registers.cpp (source / functions) Coverage Total Hit
Test: mu2edaq.info.cleaned Lines: 0.0 % 4560 0
Test Date: 2026-09-10 01:53:42 Functions: 0.0 % 670 0

            Line data    Source code
       1              : #include "DTC_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 string
       9              : 
      10              : #include "TRACE/tracemf.h"
      11              : 
      12              : #define TLVL_ResetDTC TLVL_DEBUG + 5
      13              : #define TLVL_AutogenDRP TLVL_DEBUG + 6
      14              : #define TLVL_SERDESReset TLVL_DEBUG + 7
      15              : #define TLVL_CalculateFreq TLVL_DEBUG + 8
      16              : #define TLVL_Detail TLVL_DEBUG + 11
      17              : #define TLVL_ReadRegister TLVL_DEBUG + 20
      18              : 
      19              : #include "dtcInterfaceLib/otsStyleCoutMacros.h"
      20              : 
      21              : #undef __COUT_HDR__
      22              : #define __COUT_HDR__ "DTC " << this->getDeviceUID() << ": "
      23              : 
      24              : /// <summary>
      25              : /// Construct an instance of the DTC register map
      26              : /// </summary>
      27              : /// <param name="mode">Default: DTC_SimMode_Disabled; The simulation mode of the DTC</param>
      28              : /// <param name="dtc">DTC card index to use</param>
      29              : /// <param name="simFileName">Name to use for simulated DTC memory file, if needed</param>
      30              : /// <param name="rocMask">Nibble-mask for enabled ROCs. Ex. 0x1011 enables ROC0, 1, and 3</param>
      31              : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will
      32              : /// throw an exception if the DTC firmware does not match (Default: "")</param>
      33              : /// <param name="skipInit">Whether to skip initialization phase for reading DTC out in current state</param>
      34            0 : DTCLib::DTC_Registers::DTC_Registers(DTC_SimMode mode, int dtc, std::string simFileName, unsigned rocMask, std::string expectedDesignVersion,
      35            0 :                                                                          bool skipInit, const std::string& uid)
      36            0 :         : simMode_(mode), usingDetectorEmulator_(false), dmaSize_(64)
      37              : {
      38            0 :         TLOG(TLVL_TRACE) << "CONSTRUCTOR";
      39              : 
      40            0 :         auto sim = getenv("DTCLIB_SIM_ENABLE");
      41            0 :         if (sim != nullptr)
      42              :         {
      43            0 :                 auto simstr = std::string(sim);
      44            0 :                 simMode_ = DTC_SimModeConverter::ConvertToSimMode(simstr);
      45            0 :         }
      46              : 
      47            0 :         if (dtc == -1)
      48              :         {
      49            0 :                 auto dtcE = getenv("DTCLIB_DTC");
      50            0 :                 if (dtcE != nullptr)
      51              :                 {
      52            0 :                         dtc = atoi(dtcE);
      53              :                 }
      54              :                 else
      55            0 :                         dtc = 0;
      56              :         }
      57              : 
      58            0 :         SetSimMode(expectedDesignVersion, simMode_, dtc, simFileName, rocMask, skipInit, (uid == "" ? ("DTC" + std::to_string(dtc)) : uid));
      59            0 : }  // end constructor()
      60              : 
      61              : /// <summary>
      62              : /// DTC_Registers destructor
      63              : /// </summary>
      64            0 : DTCLib::DTC_Registers::~DTC_Registers()
      65              : {
      66            0 :         TLOG(TLVL_INFO) << "DESTRUCTOR";
      67            0 :         DisableDetectorEmulator();
      68              :         // DisableDetectorEmulatorMode();
      69              :         // DisableCFOEmulation();
      70              :         // SoftReset();
      71            0 :         TLOG(TLVL_INFO) << "DESTRUCTOR end";
      72            0 : }  // end destructor()
      73              : 
      74              : /// <summary>
      75              : /// Initialize the DTC in the given SimMode.
      76              : /// </summary>
      77              : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will throw an exception if the DTC firmware does not match</param>
      78              : /// <param name="mode">Mode to set</param>
      79              : /// <param name="dtc">DTC card index to use</param>
      80              : /// <param name="simMemoryFile">Name to use for simulated DTC memory file, if needed</param>
      81              : /// <param name="rocMask">Default 0x1; The initially-enabled links. Each digit corresponds to a link, so all links = 0x111111</param>
      82              : /// <param name="skipInit">Whether to skip initializing the DTC using the SimMode. Used to read state.</param>
      83              : /// <returns></returns>
      84            0 : DTCLib::DTC_SimMode DTCLib::DTC_Registers::SetSimMode(std::string expectedDesignVersion, DTC_SimMode mode, int dtc, std::string simMemoryFile,
      85              :                                                                                                           unsigned rocMask, bool skipInit, const std::string& uid)
      86              : {
      87            0 :         simMode_ = mode;
      88            0 :         TLOG(TLVL_INFO) << "Initializing DTC device, sim mode is " << DTC_SimModeConverter(simMode_).toString() << " for uid = " << uid << ", deviceIndex = " << dtc << ", expectedDesignVersion = " << expectedDesignVersion;
      89              : 
      90            0 :         device_.init(simMode_, dtc, simMemoryFile, uid);
      91            0 :         if (expectedDesignVersion != "")
      92              :         {
      93            0 :                 uint32_t parsedExpectedVersion = 0;
      94            0 :                 std::string parsedDesignDate = "";
      95              :                 try
      96              :                 {
      97            0 :                         parsedExpectedVersion = static_cast<uint32_t>(std::stoul(expectedDesignVersion, nullptr, 16));
      98            0 :                         parsedDesignDate = ReadDesignDate(parsedExpectedVersion);
      99              :                 }
     100            0 :                 catch (...)  // illegal/non-hex expectedDesignVersion
     101              :                 {
     102            0 :                         __SS__;
     103            0 :                         ss << "Version mismatch (is Expected Firmware Version string legal?)! Expected DTC (device index #" << dtc << ") version is '" << expectedDesignVersion << "' while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
     104            0 :                         __SS_THROW__;
     105            0 :                 }
     106              : 
     107            0 :                 if (parsedExpectedVersion != ReadRegister_(CFOandDTC_Register_DesignDate))
     108              :                 {
     109            0 :                         __SS__;
     110            0 :                         ss << "Version mismatch! Expected DTC (device index #" << dtc << ") version is '" << parsedDesignDate << "' (0x" << std::hex << parsedExpectedVersion << " != 0x" << ReadRegister_(CFOandDTC_Register_DesignDate) << ") while the readback version was '" << ReadDesignVersion() << ".'" << __E__;
     111            0 :                         __SS_THROW__;
     112              :                         // throw new DTC_WrongVersionException(expectedDesignVersion, ReadDesignVersion());
     113            0 :                 }
     114            0 :         }
     115              : 
     116              :         // if (skipInit || true)
     117            0 :         if (skipInit)
     118              :         {
     119            0 :                 __COUT_INFO__ << "SKIPPING Initializing device";
     120            0 :                 return simMode_;
     121              :         }
     122              : 
     123            0 :         __COUT__ << "Initialize requested, setting device registers acccording to sim mode " << DTC_SimModeConverter(simMode_).toString();
     124              : 
     125            0 :         TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up DTC links...";
     126            0 :         for (auto link : DTC_ROC_Links)
     127              :         {
     128            0 :                 bool linkEnabled = ((rocMask >> (link * 4)) & 0x1) != 0;
     129            0 :                 if (!linkEnabled)
     130              :                 {
     131            0 :                         TLOG(TLVL_Detail) << __COUT_HDR__ << "Disabling Link " << (int)link;
     132            0 :                         DisableLink(link);
     133              : 
     134            0 :                         DisableROCEmulator(link);
     135            0 :                         SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
     136              :                 }
     137              :                 else
     138              :                 {
     139            0 :                         TLOG(TLVL_Detail) << __COUT_HDR__ << "Enabling Link " << (int)link;
     140            0 :                         EnableLink(link, DTC_LinkEnableMode(true, true));
     141              :                 }
     142              :         }
     143              : 
     144            0 :         if (simMode_ != DTC_SimMode_Disabled)
     145              :         {
     146            0 :                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation modes in Hardware...";
     147              :                 // Set up hardware simulation mode: Link 0 Tx/Rx Enabled, Loopback Enabled, ROC Emulator Enabled. All other links
     148              :                 // disabled. for (auto link : DTC_ROC_Links)
     149              :                 //      {
     150              :                 //        DisableLink(link);
     151              :                 //      }
     152              :                 //      EnableLink(DTC_Link_0, DTC_LinkEnableMode(true, true, false), DTC_ROC_0);
     153            0 :                 for (auto link : DTC_ROC_Links)
     154              :                 {
     155            0 :                         if (simMode_ == DTC_SimMode_Loopback)
     156              :                         {
     157            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of Loopback in Hardware... Link " << (int)link;
     158            0 :                                 SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_NearPCS);
     159              :                                 //                      SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
     160              :                         }
     161            0 :                         else if (simMode_ == DTC_SimMode_ROCEmulator)
     162              :                         {
     163            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of ROC in Hardware... Link " << (int)link;
     164            0 :                                 EnableROCEmulator(link);
     165              :                                 // SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
     166              :                         }
     167              :                         else
     168              :                         {
     169            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Turning off simulation in Hardware... Link " << (int)link;
     170            0 :                                 SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
     171            0 :                                 DisableROCEmulator(link);
     172              :                         }
     173              :                 }
     174            0 :                 SetCFOEmulationMode();
     175              :         }
     176              :         else
     177              :         {
     178            0 :                 ClearCFOEmulationMode();
     179              :         }
     180            0 :         ReadMinDMATransferLength();
     181              : 
     182            0 :         __COUT__ << "Done setting device registers";
     183            0 :         return simMode_;
     184              : }
     185              : 
     186              : /// <summary>
     187              : /// Read the DDR interface reset bit
     188              : /// </summary>
     189              : /// <returns>The current value of the DDR interface reset bit</returns>
     190            0 : bool DTCLib::DTC_Registers::ReadDDRInterfaceReset(std::optional<uint32_t> val)
     191              : {
     192            0 :         return !std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[1];
     193              : }
     194              : 
     195              : /// <summary>
     196              : /// Set the Reset bit in the Design Status register
     197              : /// </summary>
     198              : /// <param name="reset"></param>
     199            0 : void DTCLib::DTC_Registers::SetDDRInterfaceReset(bool reset)
     200              : {
     201            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_DesignStatus);
     202            0 :         data[1] = !reset;
     203            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_DesignStatus);
     204            0 : }
     205              : 
     206              : /// <summary>
     207              : /// Resets the DDR interface in the firmware
     208              : /// </summary>
     209            0 : void DTCLib::DTC_Registers::ResetDDRInterface()
     210              : {
     211            0 :         SetDDRInterfaceReset(true);
     212            0 :         usleep(1000);
     213            0 :         SetDDRInterfaceReset(false);
     214            0 :         while (ReadDDRInterfaceReset() && !ReadDDRAutoCalibrationDone())
     215              :         {
     216            0 :                 usleep(1000);
     217              :         }
     218            0 : }
     219              : 
     220              : /// <summary>
     221              : /// Read the DDR Auto Calibration Done bit of the Design status register
     222              : /// </summary>
     223              : /// <returns>Whether the DDR Auto Calibration is done</returns>
     224            0 : bool DTCLib::DTC_Registers::ReadDDRAutoCalibrationDone(std::optional<uint32_t> val)
     225              : {
     226            0 :         return std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[0];
     227              : }
     228              : 
     229              : /// <summary>
     230              : /// Formats the register's current value for register dumps
     231              : /// </summary>
     232              : /// <returns>RegisterFormatter object containing register information</returns>
     233            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDesignStatus()
     234              : {
     235            0 :         auto form = CreateFormatter(CFOandDTC_Register_DesignStatus);
     236            0 :         form.description = "Control and Status";
     237            0 :         form.vals.push_back(std::string("Reset DDR Interface:       [") + (ReadDDRInterfaceReset(form.value) ? "x" : " ") + "]");
     238            0 :         form.vals.push_back(std::string("DDR Auto-Calibration Done: [") + (ReadDDRAutoCalibrationDone(form.value) ? "x" : " ") + "]");
     239            0 :         return form;
     240            0 : }
     241              : 
     242              : /// <summary>
     243              : /// Enable the DTC CFO Emulator
     244              : /// Parameters for the CFO Emulator, such as count and starting timestamp, must be set before enabling.
     245              : /// </summary>
     246            0 : void DTCLib::DTC_Registers::EnableCFOEmulation()
     247              : {
     248            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     249            0 :         data[30] = 1;
     250            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     251            0 : }
     252              : 
     253              : /// <summary>
     254              : /// Disable the DTC CFO Emulator
     255              : /// </summary>
     256            0 : void DTCLib::DTC_Registers::DisableCFOEmulation()
     257              : {
     258            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     259            0 :         data[30] = 0;
     260            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     261            0 : }
     262              : 
     263              : /// <summary>
     264              : /// Reads the current state of the DTC CFO Emulator
     265              : /// </summary>
     266              : /// <returns>True if the emulator is enabled, false otherwise</returns>
     267            0 : bool DTCLib::DTC_Registers::ReadCFOEmulationEnabled(std::optional<uint32_t> val)
     268              : {
     269            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     270            0 :         return dataSet[30];
     271              : }
     272              : 
     273              : /// <summary>
     274              : /// Enable CFO Loopback. CFO packets will be returned to the CFO, for delay calculation.
     275              : /// </summary>
     276            0 : void DTCLib::DTC_Registers::EnableCFOLoopback()
     277              : {
     278            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     279            0 :         data[28] = 0;  // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
     280            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     281            0 : }
     282              : 
     283              : /// <summary>
     284              : /// Disable CFO Loopback. CFO packets will be transmitted instead to the next DTC (Normal operation)
     285              : /// </summary>
     286            0 : void DTCLib::DTC_Registers::DisableCFOLoopback()
     287              : {
     288            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     289            0 :         data[28] = 1;  // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
     290            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     291            0 : }
     292              : 
     293              : /// <summary>
     294              : /// Read the value of the CFO Link Loopback bit
     295              : /// </summary>
     296              : /// <returns>Value of the bit</returns>
     297            0 : bool DTCLib::DTC_Registers::ReadCFOLoopback(std::optional<uint32_t> val)
     298              : {
     299            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     300            0 :         return dataSet[28];
     301              : }
     302              : 
     303              : /// <summary>
     304              : /// Resets the DDR Write pointer to 0
     305              : /// </summary>
     306            0 : void DTCLib::DTC_Registers::ResetDDRWriteAddress()
     307              : {
     308            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     309            0 :         data[27] = 1;
     310            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     311            0 :         usleep(1000);
     312            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     313            0 :         data[27] = 0;
     314            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     315            0 : }
     316              : 
     317              : /// <summary>
     318              : /// Determine whether a DDR Write Pointer reset is in progress
     319              : /// </summary>
     320              : /// <returns>True if the DDR Write pointer is resetting, false otherwise</returns>
     321            0 : bool DTCLib::DTC_Registers::ReadResetDDRWriteAddress(std::optional<uint32_t> val)
     322              : {
     323            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     324            0 :         return data[27];
     325              : }
     326              : 
     327              : /// <summary>
     328              : /// Reset the DDR Read pointer to 0
     329              : /// </summary>
     330            0 : void DTCLib::DTC_Registers::ResetDDRReadAddress()
     331              : {
     332            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     333            0 :         data[26] = 1;
     334            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     335            0 :         usleep(1000);
     336            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     337            0 :         data[26] = 0;
     338            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     339            0 : }
     340              : 
     341              : /// <summary>
     342              : /// Determine whether the DDR Read pointer is currently being reset.
     343              : /// </summary>
     344              : /// <returns>True if the read pointer is currently being reset, false otherwise</returns>
     345            0 : bool DTCLib::DTC_Registers::ReadResetDDRReadAddress(std::optional<uint32_t> val)
     346              : {
     347            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     348            0 :         return data[26];
     349              : }
     350              : 
     351              : /// <summary>
     352              : /// Reset the DDR memory interface
     353              : /// </summary>
     354            0 : void DTCLib::DTC_Registers::ResetDDR()
     355              : {
     356            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     357            0 :         data[25] = 1;
     358            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     359            0 :         usleep(1000);
     360            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     361            0 :         data[25] = 0;
     362            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     363            0 : }
     364              : 
     365              : /// <summary>
     366              : /// Determine whether the DDR memory interface is currently being reset
     367              : /// </summary>
     368              : /// <returns>True if the DDR memory interface is currently being reset, false otherwise</returns>
     369            0 : bool DTCLib::DTC_Registers::ReadResetDDR(std::optional<uint32_t> val)
     370              : {
     371            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     372            0 :         return data[25];
     373              : }
     374              : 
     375              : /// <summary>
     376              : /// Enable sending Data Request packets from the DTC CFO Emulator with every
     377              : /// Readout Request
     378              : /// </summary>
     379            0 : void DTCLib::DTC_Registers::EnableCFOEmulatorDRP()
     380              : {
     381            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     382            0 :         data[24] = 1;
     383            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     384            0 : }
     385              : 
     386              : /// <summary>
     387              : /// Disable sending Data Request packets from the DTC CFO Emulator with every
     388              : /// Readout Request
     389              : /// </summary>
     390            0 : void DTCLib::DTC_Registers::DisableCFOEmulatorDRP()
     391              : {
     392            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     393            0 :         data[24] = 0;
     394            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     395            0 : }
     396              : 
     397              : /// <summary>
     398              : /// Read whether the DTC CFO Emulator is sending Data Request packets with every readout request
     399              : /// </summary>
     400              : /// <returns>True if the DTC CFO Emulator is sending Data Request packets with every readout request, false
     401              : /// otherwise</returns>
     402            0 : bool DTCLib::DTC_Registers::ReadCFOEmulatorDRP(std::optional<uint32_t> val)
     403              : {
     404            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     405            0 :         return data[24];
     406              : }
     407              : 
     408              : /// <summary>
     409              : /// Enable automatically generating Data Request packets when heartbeats are received
     410              : /// </summary>
     411            0 : void DTCLib::DTC_Registers::EnableAutogenDRP()
     412              : {
     413            0 :         TLOG(TLVL_AutogenDRP) << __COUT_HDR__ << "EnableAutogenDRP start";
     414            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     415            0 :         data[23] = 1;
     416            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     417            0 : }
     418              : 
     419              : /// <summary>
     420              : /// Disable automatically generating Data Request packets when heartbeats are received
     421              : /// </summary>
     422            0 : void DTCLib::DTC_Registers::DisableAutogenDRP()
     423              : {
     424            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     425            0 :         data[23] = 0;
     426            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     427            0 : }
     428              : 
     429              : /// <summary>
     430              : /// Read whether Data Request packets are generated by the DTC when heartbeats are received
     431              : /// </summary>
     432              : /// <returns>True if Data Request packets are generated by the DTC when heartbeats are received, false otherwise</returns>
     433            0 : bool DTCLib::DTC_Registers::ReadAutogenDRP(std::optional<uint32_t> val)
     434              : {
     435            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     436            0 :         return data[23];
     437              : }
     438              : 
     439              : /// <summary>
     440              : /// Enable receiving Data Request Packets from the DTCLib on DMA Channel 0
     441              : /// Possibly obsolete, ask Rick before using
     442              : /// </summary>
     443            0 : void DTCLib::DTC_Registers::EnableSoftwareDRP()
     444              : {
     445            0 :         DisableAutogenDRP();
     446            0 : }
     447              : 
     448              : /// <summary>
     449              : /// Disable receiving Data Request Packets from the DTCLib on DMA Channel 0
     450              : /// Possibly obsolete, ask Rick before using
     451              : /// </summary>
     452            0 : void DTCLib::DTC_Registers::DisableSoftwareDRP()
     453              : {
     454            0 :         EnableAutogenDRP();
     455            0 : }
     456              : //      std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     457              : //      data[22] = 0;
     458              : //      WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     459              : // }
     460              : 
     461              : /// <summary>
     462              : /// Read whether receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled
     463              : /// </summary>
     464              : /// <returns>True if receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled, false
     465              : /// otherwise</returns>
     466            0 : bool DTCLib::DTC_Registers::ReadSoftwareDRP(std::optional<uint32_t> val)
     467              : {
     468            0 :         return !ReadAutogenDRP(val);
     469              : }
     470              : 
     471              : /// <summary>
     472              : /// Enable kill of ROCs on 10x timeouts
     473              : /// </summary>
     474            0 : void DTCLib::DTC_Registers::EnableKillTimeoutROCs()
     475              : {
     476            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     477            0 :         data[22] = 1;
     478            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     479            0 : }
     480              : 
     481              : /// <summary>
     482              : /// Disable kill of ROCs on 10x timeouts
     483              : /// </summary>
     484            0 : void DTCLib::DTC_Registers::DisableKillTimeoutROCs()
     485              : {
     486            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     487            0 :         data[22] = 0;
     488            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     489            0 : }
     490              : 
     491              : /// <summary>
     492              : /// Read whether kill of ROCs on 10x timeouts is enabled
     493              : /// </summary>
     494              : /// <returns>True if kill of ROCs on 10x timeouts is enabled, false otherwise</returns>
     495            0 : bool DTCLib::DTC_Registers::ReadKillTimeoutROCs(std::optional<uint32_t> val)
     496              : {
     497            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     498            0 :         return data[22];
     499              : }
     500              : 
     501              : /// <summary>
     502              : /// Reset the PCIe interface
     503              : /// </summary>
     504            0 : void DTCLib::DTC_Registers::ResetPCIe()
     505              : {
     506            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     507              :         // data[21] = 1;  // no longer connected in firmware
     508              :         // data[20] = 1;  // no longer connected in firmware
     509            0 :         data[11] = 1;
     510            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     511            0 :         usleep(1000);
     512            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     513              :         // data[21] = 0;
     514              :         // data[20] = 0;
     515            0 :         data[11] = 0;
     516            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     517              : 
     518              :         // Note the DTC instance likely needs to be reinitialized on a firmware-DMA reset to realign pointers:
     519              :         // e.g. device_.initDMAEngine();
     520            0 : }
     521              : 
     522              : /// <summary>
     523              : /// Determine whether the PCIe interface is currently being reset
     524              : /// </summary>
     525              : /// <returns>True if the PCIe interface is currently being reset, false otherwise</returns>
     526            0 : bool DTCLib::DTC_Registers::ReadResetPCIe(std::optional<uint32_t> val)
     527              : {
     528            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     529            0 :         return data[21];
     530              : }
     531              : 
     532              : /// <summary>
     533              : /// Enable the All LED bits in Control register
     534              : /// </summary>
     535            0 : void DTCLib::DTC_Registers::EnableLEDs()
     536              : {
     537            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     538            0 :         data[16] = 1;
     539            0 :         data[17] = 1;
     540            0 :         data[18] = 1;
     541            0 :         data[19] = 1;
     542            0 :         data[20] = 1;
     543            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     544            0 : }
     545              : 
     546              : /// <summary>
     547              : /// Disable the All LED bits in Control register
     548              : /// </summary>
     549            0 : void DTCLib::DTC_Registers::DisableLEDs()
     550              : {
     551            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     552            0 :         data[16] = 0;
     553            0 :         data[17] = 0;
     554            0 :         data[18] = 0;
     555            0 :         data[19] = 0;
     556            0 :         data[20] = 0;
     557            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     558            0 : }
     559              : 
     560              : /// <summary>
     561              : /// Enable the All LED bits in Control register
     562              : /// </summary>
     563            0 : void DTCLib::DTC_Registers::FlashLEDs()
     564              : {
     565            0 :         DisableLEDs();
     566            0 :         sleep(1);
     567            0 :         EnableLEDs();
     568            0 :         sleep(1);
     569            0 :         DisableLEDs();
     570            0 : }
     571              : 
     572              : /// <summary>
     573              : /// Enable the Down LED0 Control register bit
     574              : /// </summary>
     575            0 : void DTCLib::DTC_Registers::EnableDownLED0()
     576              : {
     577            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     578            0 :         data[19] = 1;
     579            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     580            0 : }
     581              : 
     582              : /// <summary>
     583              : /// Disable the Down LED0 Control register bit
     584              : /// </summary>
     585            0 : void DTCLib::DTC_Registers::DisableDownLED0()
     586              : {
     587            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     588            0 :         data[19] = 0;
     589            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     590            0 : }
     591              : 
     592              : /// <summary>
     593              : /// Read the state of the Down LED0 Control register bit
     594              : /// </summary>
     595              : /// <returns>Whether the Down LED0 bit is set</returns>
     596            0 : bool DTCLib::DTC_Registers::ReadDownLED0State(std::optional<uint32_t> val)
     597              : {
     598            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     599            0 :         return data[19];
     600              : }
     601              : /// <summary>
     602              : /// Enable the Up LED1 Control register bit
     603              : /// </summary>
     604            0 : void DTCLib::DTC_Registers::EnableUpLED1()
     605              : {
     606            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     607            0 :         data[18] = 1;
     608            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     609            0 : }
     610              : 
     611              : /// <summary>
     612              : /// Disable the Up LED1 Control register bit
     613              : /// </summary>
     614            0 : void DTCLib::DTC_Registers::DisableUpLED1()
     615              : {
     616            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     617            0 :         data[18] = 0;
     618            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     619            0 : }
     620              : 
     621              : /// <summary>
     622              : /// Read the state of the Up LED1 Control register bit
     623              : /// </summary>
     624              : /// <returns>Whether the Up LED1 bit is set</returns>
     625            0 : bool DTCLib::DTC_Registers::ReadUpLED1State(std::optional<uint32_t> val)
     626              : {
     627            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     628            0 :         return data[18];
     629              : }
     630              : /// <summary>
     631              : /// Enable the Up LED0 Control register bit
     632              : /// </summary>
     633            0 : void DTCLib::DTC_Registers::EnableUpLED0()
     634              : {
     635            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     636            0 :         data[17] = 1;
     637            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     638            0 : }
     639              : 
     640              : /// <summary>
     641              : /// Disable the Up LED0 Control register bit
     642              : /// </summary>
     643            0 : void DTCLib::DTC_Registers::DisableUpLED0()
     644              : {
     645            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     646            0 :         data[17] = 0;
     647            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     648            0 : }
     649              : 
     650              : /// <summary>
     651              : /// Read the state of the Up LED0 Control register bit
     652              : /// </summary>
     653              : /// <returns>Whether the Up LED0 bit is set</returns>
     654            0 : bool DTCLib::DTC_Registers::ReadUpLED0State(std::optional<uint32_t> val)
     655              : {
     656            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     657            0 :         return data[17];
     658              : }
     659              : 
     660              : /// <summary>
     661              : /// Enable the LED6 Control register bit
     662              : /// </summary>
     663            0 : void DTCLib::DTC_Registers::EnableLED6()
     664              : {
     665            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     666            0 :         data[16] = 1;
     667            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     668            0 : }
     669              : 
     670              : /// <summary>
     671              : /// Disable the LED6 Control register bit
     672              : /// </summary>
     673            0 : void DTCLib::DTC_Registers::DisableLED6()
     674              : {
     675            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     676            0 :         data[16] = 0;
     677            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     678            0 : }
     679              : 
     680              : /// <summary>
     681              : /// Read the state of the LED6 Control register bit
     682              : /// </summary>
     683              : /// <returns>Whether the LED6 bit is set</returns>
     684            0 : bool DTCLib::DTC_Registers::ReadLED6State(std::optional<uint32_t> val)
     685              : {
     686            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     687            0 :         return data[16];
     688              : }
     689              : 
     690              : /// <summary>
     691              : /// Enable CFO Emulation mode.
     692              : /// </summary>
     693            0 : void DTCLib::DTC_Registers::SetCFOEmulationMode()
     694              : {
     695            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     696            0 :         data[15] = 1;
     697            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     698            0 : }
     699              : 
     700              : /// <summary>
     701              : /// Disable CFO Emulation mode.
     702              : /// </summary>
     703            0 : void DTCLib::DTC_Registers::ClearCFOEmulationMode()
     704              : {
     705            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     706            0 :         data[15] = 0;
     707            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     708            0 : }
     709              : 
     710              : /// <summary>
     711              : /// Read the state of the CFO Emulation Mode bit
     712              : /// </summary>
     713              : /// <returns>Whether CFO Emulation Mode is enabled</returns>
     714            0 : bool DTCLib::DTC_Registers::ReadCFOEmulationMode(std::optional<uint32_t> val)
     715              : {
     716            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     717            0 :         return data[15];
     718              : }
     719              : 
     720            0 : void DTCLib::DTC_Registers::SetDataFilterEnable()
     721              : {
     722            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     723            0 :         data[13] = 1;
     724            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     725            0 : }
     726              : 
     727            0 : void DTCLib::DTC_Registers::ClearDataFilterEnable()
     728              : {
     729            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     730            0 :         data[13] = 0;
     731            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     732            0 : }
     733              : 
     734            0 : bool DTCLib::DTC_Registers::ReadDataFilterEnable(std::optional<uint32_t> val)
     735              : {
     736            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     737            0 :         return data[13];
     738              : }
     739              : 
     740            0 : void DTCLib::DTC_Registers::SetDRPPrefetchEnable()
     741              : {
     742            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     743            0 :         data[12] = 1;
     744            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     745            0 : }
     746              : 
     747            0 : void DTCLib::DTC_Registers::ClearDRPPrefetchEnable()
     748              : {
     749            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     750            0 :         data[12] = 0;
     751            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     752            0 : }
     753              : 
     754            0 : bool DTCLib::DTC_Registers::ReadDRPPrefetchEnable(std::optional<uint32_t> val)
     755              : {
     756            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     757            0 :         return data[12];
     758              : }
     759              : 
     760            0 : void DTCLib::DTC_Registers::ROCInterfaceSoftReset()
     761              : {
     762            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     763            0 :         data[12] = 1;
     764            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     765            0 :         usleep(100000);
     766            0 :         data[12] = 0;
     767            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     768            0 : }
     769              : 
     770            0 : bool DTCLib::DTC_Registers::ReadROCInterfaceSoftReset(std::optional<uint32_t> val)
     771              : {
     772            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     773            0 :         return data[11];
     774              : }
     775              : 
     776            0 : void DTCLib::DTC_Registers::EnableDropDataToEmulateEventBuilding()
     777              : {
     778            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     779            0 :         data[10] = 1;
     780            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     781            0 : }
     782              : 
     783            0 : void DTCLib::DTC_Registers::DisableDropDataToEmulateEventBuilding()
     784              : {
     785            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     786            0 :         data[10] = 0;
     787            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     788            0 : }
     789              : 
     790            0 : bool DTCLib::DTC_Registers::ReadDropDataToEmulateEventBuilding(std::optional<uint32_t> val)
     791              : {
     792            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     793            0 :         return data[10];
     794              : }
     795              : 
     796              : /// This offset should be set 'permanently' for the DTC in response to
     797              : ///             the sample measurement at bits [18:16] of DTC_Register_CFOLinkErrorFlags
     798            0 : void DTCLib::DTC_Registers::SetCFOSamplePermanentOffset(int permanentOffset)
     799              : {
     800              :         // do not write more bits because high bits, in older versions were the error clear latch... ReadRegister_(DTC_Register_CFOLinkErrorFlags);
     801              :         // set only 3-bits [2:0]
     802            0 :         WriteRegister_(permanentOffset & 7, DTC_Register_CFOLinkErrorFlags);
     803            0 : }  // end SetCFOSamplePermanentOffset()
     804              : 
     805            0 : int DTCLib::DTC_Registers::ReadCFOSamplePermanentOffset(std::optional<uint32_t> val)
     806              : {
     807            0 :         uint32_t setting = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
     808            0 :         setting &= 7;
     809            0 :         if (setting > 3)
     810            0 :                 setting = -8 + setting;
     811            0 :         return setting;  // return 3-bit value handling of [-2,2]
     812              : }  // end ReadCFOSamplePermanentOffset()
     813              : 
     814              : /// @brief Set edge selection of RTF clock and external CFO rx -> tx data
     815              : /// @param forceCFOedge is a 2-bit value
     816            0 : void DTCLib::DTC_Registers::SetExternalCFOSampleEdgeMode(int forceCFOedge)
     817              : {
     818            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     819              : 
     820            0 :         data[6] = ((forceCFOedge >> 1) & 1) ? 0 : 1;  // invert bit[1], DTC control bit [6] := 1 for forced, 0 for auto
     821            0 :         data[5] = (forceCFOedge & 1);                 // DTC control bit [5] := 1 for falling-edge, 0 for rising-edge
     822            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     823            0 : }  // end SetExternalCFOSampleEdgeMode()
     824              : 
     825            0 : int DTCLib::DTC_Registers::ReadExternalCFOSampleEdgeMode(std::optional<uint32_t> val)
     826              : {
     827            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     828            0 :         return (data[6] << 1) | data[5];
     829              : }  // end ReadExternalCFOSampleEdgeMode()
     830              : 
     831              : /// @brief Toggle only the CFO sample clock edge (Control Register bit 5), leaving the
     832              : ///        forced/auto select (bit 6) untouched.
     833              : /// @return the new edge bit value: 0 = rising-edge (posedge), 1 = falling-edge (negedge)
     834            0 : int DTCLib::DTC_Registers::ToggleExternalCFOSampleEdge()
     835              : {
     836            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     837            0 :         data[5] = !data[5];  // DTC control bit [5]: 1 for falling-edge, 0 for rising-edge
     838            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     839            0 :         return data[5];
     840              : }  // end ToggleExternalCFOSampleEdge()
     841              : 
     842            0 : void DTCLib::DTC_Registers::SetRTFPunchedClockEdge(bool posedge)
     843              : {
     844            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     845            0 :         data[7] = posedge ? 1 : 0;
     846            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     847            0 : }
     848              : 
     849            0 : bool DTCLib::DTC_Registers::ReadRTFPunchedClockEdge(std::optional<uint32_t> val)
     850              : {
     851            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     852            0 :         return data[7];
     853              : }
     854              : 
     855              : /// @return the new edge bit value: 0 = negedge, 1 = posedge
     856            0 : int DTCLib::DTC_Registers::ToggleRTFPunchedClockEdge()
     857              : {
     858            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     859            0 :         data[7] = !data[7];
     860            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     861            0 :         return data[7];
     862              : }
     863              : 
     864            0 : void DTCLib::DTC_Registers::SetExternalFanoutClockInput()
     865              : {
     866            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     867            0 :         data[4] = 1;
     868            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     869            0 : }
     870              : 
     871            0 : void DTCLib::DTC_Registers::SetInternalFanoutClockInput()
     872              : {
     873            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     874            0 :         data[4] = 0;
     875            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     876            0 : }
     877              : 
     878            0 : bool DTCLib::DTC_Registers::ReadFanoutClockInput(std::optional<uint32_t> val)
     879              : {
     880            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     881            0 :         return data[4];
     882              : }
     883              : 
     884              : /// <summary>
     885              : /// Enable receiving DCS packets.
     886              : /// </summary>
     887            0 : void DTCLib::DTC_Registers::EnableDCSReception()
     888              : {
     889            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     890            0 :         data[2] = 1;
     891            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     892            0 : }
     893              : /// <summary>
     894              : /// Disable receiving DCS packets. Any DCS packets received will be ignored
     895              : /// </summary>
     896            0 : void DTCLib::DTC_Registers::DisableDCSReception()
     897              : {
     898            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     899            0 :         data[2] = 0;
     900            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     901            0 : }
     902              : /// <summary>
     903              : /// Read the status of the DCS Enable bit
     904              : /// </summary>
     905              : /// <returns>Whether DCS packet reception is enabled</returns>
     906            0 : bool DTCLib::DTC_Registers::ReadDCSReception(std::optional<uint32_t> val)
     907              : {
     908            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     909            0 :         return data[2];
     910              : }
     911              : 
     912              : /// <summary>
     913              : /// Formats the register's current value for register dumps
     914              : /// </summary>
     915              : /// <returns>RegisterFormatter object containing register information</returns>
     916            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDTCControl()
     917              : {
     918            0 :         auto form = CreateFormatter(CFOandDTC_Register_Control);
     919            0 :         form.description = "DTC Control";
     920            0 :         form.vals.push_back("([ x = 1 (hi) ])");
     921              : 
     922              :         // ~~~  DTC Control Register (0x9100) ~~~
     923              :         // Bit Position Mode    Default Value   Description
     924              :         // 31   WO      0b0     DTC Soft Reset (Self-clearing)
     925              :         // 30   RW      0b0     CFO Emulation Enable
     926              :         // 29   RW      0b0     Reserved (Formerly CFO Emulation Enable Continuous)
     927              :         // 28   RW      0b0     CFO Link Output Control
     928              :         // 27   RW      0b0     Reset DDR Write Address
     929              :         // 26   RW      0b0     Reserved (Formerly Reset DDR Read Address)
     930              :         // 25   RW      0b0     Reserved (DDR Interface Reset)
     931              :         // 24   RW      0b0     CFO Emulator DRP Enable
     932              :         // 23   RW      0b0     DTC Autogenerate DRP Enable
     933              :         // 22   RW      0b0     Reserved (Formerly Software DRP Enable)
     934              :         // 21   RW      0b0     Reserved (Formerly local EVB Source Buffer Reset)
     935              :         // 20   RW      0b0     Reserved (Formerly EVB DMA Buffer Reset)
     936              :         // 19   RW      0b0     Down LED 0
     937              :         // 18   RW      0b0     Up LED 1
     938              :         // 17   RW      0b0     Up LED 0
     939              :         // 16   RW      0b0     LED 7
     940              :         // 15   RW      0b0     CFO Emulation Mode
     941              :         // 14   RW      0b0     Reserved (Formerly EVB Debug Count Enable)
     942              :         // 13   RW      0b0     Reserved (Formerly Trigger Filter Enable)
     943              :         // 12   RW      0b0     DRP Prefetch Enable
     944              :         // 11   RW      0b0     Reserved (Formerly EVM Buffer Reset)
     945              :         // 10   RW      0b0     Drop Subevent Data to Emulate Hardware Event Building Reserved (Formerly Sequence Number Disable)
     946              :         // 9    RW      0b0     Punch Enable on RJ-45 Output
     947              :         // 8    RW      0b0     SERDES Global Reset
     948              :         // 7    RW      0b0     RTF Punched Clock Edge Select (0=negedge, 1=posedge)
     949              :         // 6    RW      0b0     Do Force External CFO Sample Edge (Formerly RX Packet Error Feedback Enable)
     950              :         // 5    RW      0b0     Force External CFO Sample Edge Select (Formerly Comma Tolerance Enable)
     951              :         // 4    RW      0b0     Fanout Clock Input Select
     952              :         // 3    RW      0b0     CFO Emulator Loopback Test Launch Control
     953              :         // 2    RW      0b0     DCS Enable
     954              :         // 1    RW      0b0     Reserved (Formerly SERDES Comma Align)
     955              :         // 0    WO      0b0     DTC Hard Reset (Self-clearing)
     956              : 
     957            0 :         form.vals.push_back(std::string("Bit-31 DTC Soft Reset (Self-clearing):       [") + (ReadSoftReset(form.value) ? "x" : " ") + "]");
     958            0 :         form.vals.push_back(std::string("Bit-30 CFO Emulation Enable:                 [") + (ReadCFOEmulationEnabled(form.value) ? "x" : " ") + "]");
     959            0 :         form.vals.push_back(std::string("Bit-28 CFO Link Timing Card not-in-Loopback: [") + (ReadCFOLoopback(form.value) ? "x" : " ") + "]");
     960              :         // form.vals.push_back(std::string("Bit-27 Reset DDR Write Address:         [") + (ReadResetDDRWriteAddress(form.value) ? "x" : " ") + "]");
     961              :         // form.vals.push_back(std::string("Bit-26 Reset DDR Read Address:          [") + (ReadResetDDRReadAddress(form.value) ? "x" : " ") + "]");
     962              :         // form.vals.push_back(std::string("Bit-25 Reset DDR Interface:             [") + (ReadResetDDR(form.value) ? "x" : " ") + "]");
     963              :         // form.vals.push_back(std::string("Bit-24 CFO Emulator DRP Enable:         [") + (ReadCFOEmulatorDRP(form.value) ? "x" : " ") + "]");
     964            0 :         form.vals.push_back(std::string("Bit-23 DTC Autogenerate DRP:                 [") + (ReadAutogenDRP(form.value) ? "x" : " ") + "]");
     965              :         // Bit-22 is currently defined as "Kill ROCs on 10x Timeouts" (legacy Software DRP meaning no longer applies).
     966            0 :         form.vals.push_back(std::string("Bit-22 Kill ROCs on 10x Timeouts:            [") + (ReadKillTimeoutROCs(form.value) ? "x" : " ") + "]");
     967            0 :         form.vals.push_back(std::string("Bit-19 Down LED 0:                           [") + (ReadDownLED0State(form.value) ? "x" : " ") + "]");
     968            0 :         form.vals.push_back(std::string("Bit-18 Up LED 1:                             [") + (ReadUpLED1State(form.value) ? "x" : " ") + "]");
     969            0 :         form.vals.push_back(std::string("Bit-17 Up LED 0:                             [") + (ReadUpLED0State(form.value) ? "x" : " ") + "]");
     970            0 :         form.vals.push_back(std::string("Bit-16 LED 6:                                [") + (ReadLED6State(form.value) ? "x" : " ") + "]");
     971            0 :         form.vals.push_back(std::string("Bit-15 CFO Emulation Mode:                   [") + (ReadCFOEmulationMode(form.value) ? "x" : " ") + "]");
     972              :         // form.vals.push_back(std::string("Bit-31 Data Filter Enable:              [") + (ReadDataFilterEnable(form.value) ? "x" : " ") + "]");
     973            0 :         form.vals.push_back(std::string("Bit-12 DRP Prefetch Enable:                  [") + (ReadDRPPrefetchEnable(form.value) ? "x" : " ") + "]");
     974            0 :         form.vals.push_back(std::string("Bit-10 Skip-by-32 Subevent Readout Enable:   [") + (ReadDropDataToEmulateEventBuilding(form.value) ? "x" : " ") + "]");
     975              :         // form.vals.push_back(std::string("Bit-31 ROC Interface Soft Reset:        [") + (ReadROCInterfaceSoftReset(form.value) ? "x" : " ") + "]");
     976              :         // form.vals.push_back(std::string("Bit-31 Sequence Number Disable:         [") + (ReadSequenceNumberDisable(form.value) ? "x" : " ") + "]");
     977              :         // form.vals.push_back(std::string("Bit-31 Punch Enable:                    [") + (ReadPunchEnable(form.value) ? "x" : " ") + "]");
     978              : 
     979            0 :         form.vals.push_back(std::string("Bit-09 Punched Clock Enable:                 [") + (CFOandDTC_Registers::ReadPunchEnable(form.value) ? "x" : " ") + "]");
     980            0 :         form.vals.push_back(std::string("Bit-08 SERDES Global Reset:                  [") + (CFOandDTC_Registers::ReadResetSERDES(form.value) ? "x" : " ") + "]");
     981            0 :         form.vals.push_back(std::string("Bit-07 RTF Punched Clock Edge Select:        [") + (ReadRTFPunchedClockEdge(form.value) ? "posedge" : "negedge") + "]");
     982              : 
     983            0 :         form.vals.push_back(std::string("Bit-06 Enable CFO-RTF Offset Control:        [") + (((ReadExternalCFOSampleEdgeMode(form.value) >> 1) & 1) ? "x" : " ") + "]");
     984            0 :         form.vals.push_back(std::string("Bit-05 CFO-RTF Edge Select:                  [") + ((ReadExternalCFOSampleEdgeMode(form.value) & 1) ? "negedge" : "posedge") + "]");
     985              : 
     986              :         // form.vals.push_back(std::string("Bit-31 RX Packet Error Feedback Enable: [") + (ReadRxPacketErrorFeedbackEnable(form.value) ? "x" : " ") + "]");
     987              :         // form.vals.push_back(std::string("Bit-31 Comma Tolerance Enable:          [") + (ReadCommaToleranceEnable(form.value) ? "x" : " ") + "]");
     988            0 :         form.vals.push_back(std::string("Bit-04 Fanout Clock Input Select:            [") + (ReadFanoutClockInput(form.value) ? "FMC SFP Rx" : "FPGA") + "]");
     989            0 :         form.vals.push_back(std::string("Bit-02 DCS Enable:                           [") + (ReadDCSReception(form.value) ? "x" : " ") + "]");
     990            0 :         form.vals.push_back(std::string("Bit-00 DTC Hard Reset (Self-clearing):       [") + (ReadHardReset(form.value) ? "x" : " ") + "]");
     991            0 :         return form;
     992            0 : }
     993              : 
     994              : // DMA Transfer Length Register
     995              : /// <summary>
     996              : /// Set the DMA buffer size which will automatically trigger a DMA
     997              : /// </summary>
     998              : /// <param name="length">Size, in bytes of buffer that will trigger a DMA</param>
     999            0 : void DTCLib::DTC_Registers::SetTriggerDMATransferLength(uint16_t length)
    1000              : {
    1001            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1002            0 :         data = (data & 0x0000FFFF) + (length << 16);
    1003            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
    1004            0 : }
    1005              : 
    1006              : /// <summary>
    1007              : /// Read the DMA buffer size which will automatically trigger a DMA
    1008              : /// </summary>
    1009              : /// <returns>The DMA buffer size which will automatically trigger a DMA, in bytes</returns>
    1010            0 : uint16_t DTCLib::DTC_Registers::ReadTriggerDMATransferLength(std::optional<uint32_t> val)
    1011              : {
    1012            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1013            0 :         data >>= 16;
    1014            0 :         return static_cast<uint16_t>(data);
    1015              : }
    1016              : 
    1017              : /// <summary>
    1018              : /// Set the minimum DMA transfer size. Absolute minimum is 64 bytes.
    1019              : /// Buffers smaller than this size will be padded to the minimum.
    1020              : /// </summary>
    1021              : /// <param name="length">Size, in bytes, of the minimum DMA transfer buffer</param>
    1022            0 : void DTCLib::DTC_Registers::SetMinDMATransferLength(uint16_t length)
    1023              : {
    1024            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1025            0 :         data = (data & 0xFFFF0000) + length;
    1026            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
    1027            0 : }
    1028              : 
    1029              : /// <summary>
    1030              : /// Read the minimum DMA transfer size.
    1031              : /// </summary>
    1032              : /// <returns>The minimum DMA size, in bytes</returns>
    1033            0 : uint16_t DTCLib::DTC_Registers::ReadMinDMATransferLength(std::optional<uint32_t> val)
    1034              : {
    1035            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1036            0 :         data = data & 0x0000FFFF;
    1037            0 :         dmaSize_ = static_cast<uint16_t>(data);
    1038            0 :         return dmaSize_;
    1039              : }
    1040              : 
    1041              : /// <summary>
    1042              : /// Formats the register's current value for register dumps
    1043              : /// </summary>
    1044              : /// <returns>RegisterFormatter object containing register information</returns>
    1045            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATransferLength()
    1046              : {
    1047            0 :         auto form = CreateFormatter(CFOandDTC_Register_DMATransferLength);
    1048            0 :         form.description = "DMA Transfer Length";
    1049            0 :         std::stringstream o;
    1050            0 :         o << "Trigger Length: 0x" << std::hex << ReadTriggerDMATransferLength(form.value);
    1051            0 :         form.vals.push_back(o.str());
    1052            0 :         std::stringstream p;
    1053            0 :         p << "Minimum Length: 0x" << std::hex << ReadMinDMATransferLength(form.value);
    1054            0 :         form.vals.push_back(p.str());
    1055            0 :         return form;
    1056            0 : }
    1057              : 
    1058              : // SERDES Loopback Enable Register
    1059              : /// <summary>
    1060              : /// Set the SERDES Loopback mode for the given link
    1061              : /// </summary>
    1062              : /// <param name="link">Link to set for</param>
    1063              : /// <param name="mode">DTC_SERDESLoopbackMode to set</param>
    1064            0 : void DTCLib::DTC_Registers::SetSERDESLoopbackMode(DTC_Link_ID const& link, const DTC_SERDESLoopbackMode& mode)
    1065              : {
    1066            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable);
    1067            0 :         std::bitset<3> modeSet = mode;
    1068            0 :         data[3 * link] = modeSet[0];
    1069            0 :         data[3 * link + 1] = modeSet[1];
    1070            0 :         data[3 * link + 2] = modeSet[2];
    1071            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_LoopbackEnable);
    1072            0 : }
    1073              : 
    1074              : /// <summary>
    1075              : /// Read the SERDES Loopback mode for the given link
    1076              : /// </summary>
    1077              : /// <param name="link">Link to read</param>
    1078              : /// <returns>DTC_SERDESLoopbackMode of the link</returns>
    1079            0 : DTCLib::DTC_SERDESLoopbackMode DTCLib::DTC_Registers::ReadSERDESLoopback(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1080              : {
    1081            0 :         std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable)) >> 3 * link;
    1082            0 :         return static_cast<DTC_SERDESLoopbackMode>(dataSet.to_ulong());
    1083              : }
    1084              : 
    1085              : /// <summary>
    1086              : /// Formats the register's current value for register dumps
    1087              : /// </summary>
    1088              : /// <returns>RegisterFormatter object containing register information</returns>
    1089            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESLoopbackEnable()
    1090              : {
    1091            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
    1092            0 :         form.description = "SERDES Loopback Enable";
    1093            0 :         form.vals.push_back("");  // translation
    1094            0 :         for (auto r : DTC_ROC_Links)
    1095              :         {
    1096            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " +
    1097            0 :                                                         DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(r, form.value)).toString());
    1098              :         }
    1099            0 :         form.vals.push_back(std::string("CFO:    ") +
    1100            0 :                                                 DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_CFO, form.value)).toString());
    1101            0 :         form.vals.push_back(std::string("EVB:    ") +
    1102            0 :                                                 DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_EVB, form.value)).toString());
    1103            0 :         return form;
    1104            0 : }
    1105              : 
    1106              : // Clock Status Register
    1107              : /// <summary>
    1108              : /// Read the SERDES Oscillator IIC Error Bit
    1109              : /// </summary>
    1110              : /// <returns>True if the SERDES Oscillator IIC Error is set</returns>
    1111            0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICError(std::optional<uint32_t> val)
    1112              : {
    1113            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
    1114            0 :         return dataSet[2];
    1115              : }
    1116              : 
    1117              : /// <summary>
    1118              : /// Read the DDR Oscillator IIC Error Bit
    1119              : /// </summary>
    1120              : /// <returns>True if the DDR Oscillator IIC Error is set</returns>
    1121            0 : bool DTCLib::DTC_Registers::ReadDDROscillatorIICError(std::optional<uint32_t> val)
    1122              : {
    1123            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
    1124            0 :         return dataSet[18];
    1125              : }
    1126              : 
    1127              : /// <summary>
    1128              : /// Formats the register's current value for register dumps
    1129              : /// </summary>
    1130              : /// <returns>RegisterFormatter object containing register information</returns>
    1131            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatClockOscillatorStatus()
    1132              : {
    1133            0 :         auto form = CreateFormatter(CFOandDTC_Register_ClockOscillatorStatus);
    1134            0 :         form.description = "Clock Oscillator Status";
    1135            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1136            0 :         form.vals.push_back(std::string("SERDES IIC Error:     [") + (ReadSERDESOscillatorIICError(form.value) ? "x" : " ") + "]");
    1137            0 :         form.vals.push_back(std::string("DDR IIC Error:        [") + (ReadDDROscillatorIICError(form.value) ? "x" : " ") + "]");
    1138            0 :         return form;
    1139            0 : }
    1140              : 
    1141              : // ROC Emulation Enable Register
    1142              : /// <summary>
    1143              : /// Enable the ROC emulator on the given link
    1144              : /// </summary>
    1145              : /// <param name="link">Link to enable</param>
    1146            0 : void DTCLib::DTC_Registers::EnableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
    1147              : {
    1148            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
    1149            0 :         if (link == DTC_Link_ALL)
    1150            0 :                 for (const auto& l : DTC_ROC_Links)
    1151            0 :                         dataSet[l + type * 6] = 1;
    1152              :         else
    1153            0 :                 dataSet[link + type * 6] = 1;
    1154              : 
    1155            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
    1156            0 : }
    1157              : 
    1158              : /// <summary>
    1159              : /// Disable the ROC emulator on the given link
    1160              : /// </summary>
    1161              : /// <param name="link">Link to disable</param>
    1162            0 : void DTCLib::DTC_Registers::DisableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
    1163              : {
    1164            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
    1165            0 :         if (link == DTC_Link_ALL)
    1166            0 :                 for (const auto& l : DTC_ROC_Links)
    1167            0 :                         dataSet[l + type * 6] = 0;
    1168              :         else
    1169            0 :                 dataSet[link + type * 6] = 0;
    1170              : 
    1171            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
    1172            0 : }
    1173              : 
    1174              : /// <summary>
    1175              : /// Read the state of the ROC emulator on the given link
    1176              : /// </summary>
    1177              : /// <param name="link">Link to read</param>
    1178              : /// <returns>True if the ROC Emulator is enabled on the link</returns>
    1179            0 : bool DTCLib::DTC_Registers::ReadROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type, std::optional<uint32_t> val)
    1180              : {
    1181            0 :         if (std::find(DTC_ROC_Links.begin(), DTC_ROC_Links.end(), link) == DTC_ROC_Links.end())
    1182              :         {
    1183            0 :                 __SS__ << "Illegal link specified for ROC Emulator target: " << link << __E__;
    1184            0 :                 __SS_THROW__;
    1185            0 :         }
    1186              : 
    1187            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
    1188            0 :         return dataSet[link + type * 6];
    1189              : }
    1190            0 : void DTCLib::DTC_Registers::SetROCEmulatorMask(uint32_t rocEnableMask)
    1191              : {
    1192            0 :         WriteRegister_(rocEnableMask, DTC_Register_ROCEmulationEnable);
    1193            0 : }
    1194            0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorMask(std::optional<uint32_t> val)
    1195              : {
    1196            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
    1197              : }
    1198              : 
    1199              : /// <summary>
    1200              : /// Formats the register's current value for register dumps
    1201              : /// </summary>
    1202              : /// <returns>RegisterFormatter object containing register information</returns>
    1203            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationEnable()
    1204              : {
    1205            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulationEnable);
    1206            0 :         form.description = "ROC Emulator Enable";
    1207            0 :         form.vals.push_back("       ([ Internal, Fiber-Loopback, External ])");  // translation
    1208            0 :         for (auto r : DTC_ROC_Links)
    1209            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) +
    1210            0 :                                                         ": [" + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_Internal_Emulation, form.value) ? "x" : ".") + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_FiberLoopback_Emulation, form.value) ? "x" : ".") + (ReadROCEmulator(r, DTC_ROC_Emulation_Type::ROC_External_Emulation, form.value) ? "x" : ".") + "]");
    1211              : 
    1212            0 :         return form;
    1213            0 : }
    1214              : 
    1215              : // Link Enable Register
    1216              : /// <summary>
    1217              : /// Enable Receive CFO Link
    1218              : /// </summary>
    1219            0 : void DTCLib::DTC_Registers::EnableReceiveCFOLink()
    1220              : {
    1221            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1222            0 :         data[14] = 1;
    1223            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1224            0 : }
    1225              : /// <summary>
    1226              : /// Disable Receive CFO Link
    1227              : /// </summary>
    1228            0 : void DTCLib::DTC_Registers::DisableReceiveCFOLink()
    1229              : {
    1230            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1231            0 :         data[14] = 0;
    1232            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1233            0 : }
    1234              : /// <summary>
    1235              : /// Enable Receive CFO Link
    1236              : /// </summary>
    1237            0 : void DTCLib::DTC_Registers::EnableTransmitCFOLink()
    1238              : {
    1239            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1240            0 :         data[6] = 1;
    1241            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1242            0 : }
    1243              : /// <summary>
    1244              : /// Disable Receive CFO Link
    1245              : /// </summary>
    1246            0 : void DTCLib::DTC_Registers::DisableTransmitCFOLink()
    1247              : {
    1248            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1249            0 :         data[6] = 0;
    1250            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1251            0 : }
    1252              : /// <summary>
    1253              : /// Enable a SERDES Link based on the mode tx/rx enable bits (default is enabled)
    1254              : /// </summary>
    1255              : /// <param name="link">Link to enable</param>
    1256              : /// <param name="mode">Link enable bits to set (Default: All)</param>
    1257            0 : void DTCLib::DTC_Registers::EnableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
    1258              : {
    1259            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1260            0 :         data[link] = mode.TransmitEnable;
    1261            0 :         data[link + 8] = mode.ReceiveEnable;
    1262            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1263            0 : }
    1264              : 
    1265              : /// <summary>
    1266              : /// Disable a SERDES Link
    1267              : /// The given mode bits will be UNSET
    1268              : /// </summary>
    1269              : /// <param name="link">Link to disable</param>
    1270              : /// <param name="mode">Link enable bits to unset (Default: All)</param>
    1271            0 : void DTCLib::DTC_Registers::DisableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
    1272              : {
    1273            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1274            0 :         data[link] = data[link] && !mode.TransmitEnable;
    1275            0 :         data[link + 8] = data[link + 8] && !mode.ReceiveEnable;
    1276            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1277            0 : }
    1278              : 
    1279              : /// <summary>
    1280              : /// Read the Link Enable bits for a given SERDES link
    1281              : /// </summary>
    1282              : /// <param name="link">Link to read</param>
    1283              : /// <returns>DTC_LinkEnableMode containing TX, RX, and CFO bits</returns>
    1284            0 : DTCLib::DTC_LinkEnableMode DTCLib::DTC_Registers::ReadLinkEnabled(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1285              : {
    1286            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1287            0 :         return DTC_LinkEnableMode(dataSet[link], dataSet[link + 8]);
    1288              : }
    1289            0 : uint32_t DTCLib::DTC_Registers::ReadLinkEnabledData()
    1290              : {
    1291            0 :         return ReadRegister_(CFOandDTC_Register_LinkEnable);
    1292              : }
    1293              : 
    1294            0 : bool DTCLib::DTC_Registers::ReadBlockNullHeartbeatsToROC(std::optional<uint32_t> val)
    1295              : {
    1296            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1297            0 :         return dataSet[24];
    1298              : }
    1299            0 : void DTCLib::DTC_Registers::SetBlockNullHeartbeatsToROC(bool enable)
    1300              : {
    1301            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1302            0 :         data[24] = enable;
    1303            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1304            0 : }
    1305              : 
    1306            0 : bool DTCLib::DTC_Registers::ReadResequenceNonNullEvents(std::optional<uint32_t> val)
    1307              : {
    1308            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1309            0 :         return dataSet[25];
    1310              : }
    1311            0 : void DTCLib::DTC_Registers::SetResequenceNonNullEvents(bool enable)
    1312              : {
    1313            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1314            0 :         data[25] = enable;
    1315            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1316            0 : }
    1317              : 
    1318            0 : bool DTCLib::DTC_Registers::ReadAutoGenDRPPerLink(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1319              : {
    1320            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1321            0 :         return dataSet[link + 16];
    1322              : }
    1323            0 : void DTCLib::DTC_Registers::SetAutoGenDRPPerLink(DTC_Link_ID const& link, bool enable)
    1324              : {
    1325            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1326            0 :         data[link + 16] = enable;
    1327            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1328            0 : }
    1329              : 
    1330              : /// <summary>
    1331              : /// Formats the register's current value for register dumps
    1332              : /// </summary>
    1333              : /// <returns>RegisterFormatter object containing register information</returns>
    1334            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkEnable()
    1335              : {
    1336            0 :         auto form = CreateFormatter(CFOandDTC_Register_LinkEnable);
    1337            0 :         form.description = "Link Enable";
    1338            0 :         form.vals.push_back("       ([TX, RX])");
    1339            0 :         for (auto r : DTC_ROC_Links)
    1340              :         {
    1341            0 :                 auto re = ReadLinkEnabled(r, form.value);
    1342            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.TransmitEnable ? "x" : ".") + "" +
    1343            0 :                                                         (re.ReceiveEnable ? "x" : ".") + "]");
    1344              :         }
    1345              :         {
    1346            0 :                 auto ce = ReadLinkEnabled(DTC_Link_CFO, form.value);
    1347            0 :                 form.vals.push_back(std::string("CFO:    [") + (ce.TransmitEnable ? "x" : ".") + "" +
    1348            0 :                                                         (ce.ReceiveEnable ? "x" : ".") + "]");
    1349              :         }
    1350              :         {
    1351            0 :                 auto ee = ReadLinkEnabled(DTC_Link_EVB, form.value);
    1352            0 :                 form.vals.push_back(std::string("EVB:    [") + (ee.TransmitEnable ? "x" : ".") + "" +
    1353            0 :                                                         (ee.ReceiveEnable ? "x" : ".") + "]");
    1354              :         }
    1355            0 :         form.vals.push_back(std::string("Block Null Heartbeats to ALL ROCs: [") +
    1356            0 :                                                 (ReadBlockNullHeartbeatsToROC(form.value) ? "x" : ".") + "]");
    1357            0 :         form.vals.push_back(std::string("Resequence Non-null Events for ALL ROCs:   [") +
    1358            0 :                                                 (ReadResequenceNonNullEvents(form.value) ? "x" : ".") + "]");
    1359            0 :         for (auto r : DTC_ROC_Links)
    1360              :         {
    1361            0 :                 form.vals.push_back(std::string("Auto-Gen DRP Link ") + std::to_string(r) + ": [" +
    1362            0 :                                                         (ReadAutoGenDRPPerLink(r, form.value) ? "x" : ".") + "]");
    1363              :         }
    1364            0 :         return form;
    1365            0 : }
    1366              : 
    1367              : // SERDES Reset Register
    1368              : /// <summary>
    1369              : /// Reset the SERDES TX side
    1370              : /// Will poll the Reset SERDES TX Done flag until the SERDES reset is complete
    1371              : /// </summary>
    1372              : /// <param name="link">Link to reset</param>
    1373              : /// <param name="interval">Polling interval, in microseconds</param>
    1374            0 : void DTCLib::DTC_Registers::ResetSERDESTX(DTC_Link_ID const& link, int interval)
    1375              : {
    1376            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES TX Reset Loop for Link " << link;
    1377            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1378            0 :         if (link == DTC_Link_ALL)
    1379              :         {
    1380            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1381            0 :                         data[i + 24] = 1;
    1382              :         }
    1383              :         else
    1384            0 :                 data[link + 24] = 1;
    1385            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1386              : 
    1387            0 :         usleep(interval);
    1388              : 
    1389            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1390            0 :         if (link == DTC_Link_ALL)
    1391              :         {
    1392            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1393            0 :                         data[i + 24] = 0;
    1394              :         }
    1395              :         else
    1396            0 :                 data[link + 24] = 0;
    1397            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1398              : 
    1399            0 :         auto resetDone = false;
    1400            0 :         uint32_t loops = 0;
    1401            0 :         while (!resetDone && ++loops < 10)
    1402              :         {
    1403            0 :                 usleep(interval);
    1404              : 
    1405              :                 // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
    1406            0 :                 resetDone = true;
    1407              :                 // if(link == DTC_Link_ALL)
    1408              :                 // {
    1409              :                 //      //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1410              :                 //      resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
    1411              :                 // }
    1412              :                 // else
    1413              :                 //      resetDone = ReadResetTXSERDESDone(link);
    1414              : 
    1415            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES TX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1416              :         }
    1417              : 
    1418            0 :         if (loops >= 10)
    1419              :         {
    1420            0 :                 __SS__ << "Timeout waiting for SERDES TX Reset loop.";
    1421            0 :                 __SS_THROW__;
    1422              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES TX Reset loop.");
    1423            0 :         }
    1424            0 : }
    1425              : 
    1426              : /// <summary>
    1427              : /// Read if a SERDES TX reset is currently in progress
    1428              : /// </summary>
    1429              : /// <param name="link">Link to read</param>
    1430              : /// <returns>True if a SERDES TX reset is in progress</returns>
    1431            0 : bool DTCLib::DTC_Registers::ReadResetSERDESTX(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1432              : {
    1433            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1434            0 :         return dataSet[link + 24];
    1435              : }
    1436              : 
    1437              : /// <summary>
    1438              : /// Reset the SERDES RX side
    1439              : /// Will poll the Reset SERDES RX Done flag until the SERDES reset is complete
    1440              : /// </summary>
    1441              : /// <param name="link">Link to reset</param>
    1442              : /// <param name="interval">Polling interval, in microseconds</param>
    1443            0 : void DTCLib::DTC_Registers::ResetSERDESRX(DTC_Link_ID const& link, int interval)
    1444              : {
    1445            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES RX Reset Loop for Link " << link;
    1446            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1447            0 :         if (link == DTC_Link_ALL)
    1448              :         {
    1449            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1450            0 :                         data[i + 16] = 1;
    1451              :         }
    1452              :         else
    1453            0 :                 data[link + 16] = 1;
    1454            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1455              : 
    1456            0 :         usleep(interval);
    1457              : 
    1458            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1459            0 :         if (link == DTC_Link_ALL)
    1460              :         {
    1461            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1462            0 :                         data[i + 16] = 0;
    1463              :         }
    1464              :         else
    1465            0 :                 data[link + 16] = 0;
    1466            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1467              : 
    1468            0 :         auto resetDone = false;
    1469            0 :         uint32_t loops = 0;
    1470            0 :         while (!resetDone && ++loops < 10)
    1471              :         {
    1472            0 :                 usleep(interval);
    1473              : 
    1474              :                 // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
    1475            0 :                 resetDone = true;
    1476              :                 // if(link == DTC_Link_ALL)
    1477              :                 // {
    1478              :                 //      //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1479              :                 //      resetDone = ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF;
    1480              :                 // }
    1481              :                 // else
    1482              :                 //      resetDone = ReadResetRXSERDESDone(link);
    1483              : 
    1484            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES RX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1485              :         }
    1486              : 
    1487            0 :         if (loops >= 10)
    1488              :         {
    1489            0 :                 __SS__ << "Timeout waiting for SERDES RX Reset loop.";
    1490            0 :                 __SS_THROW__;
    1491              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES RX Reset loop.");
    1492            0 :         }
    1493            0 : }
    1494              : 
    1495              : /// <summary>
    1496              : /// Read if a SERDES RX reset is currently in progress
    1497              : /// </summary>
    1498              : /// <param name="link">Link to read</param>
    1499              : /// <returns>True if a SERDES reset is in progress</returns>
    1500            0 : bool DTCLib::DTC_Registers::ReadResetSERDESRX(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1501              : {
    1502            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1503            0 :         return dataSet[link + 16];
    1504              : }
    1505              : 
    1506              : /// <summary>
    1507              : /// Reset the SERDES PLL
    1508              : /// Will poll the Reset SERDES PLL Done flag until the SERDES reset is complete
    1509              : /// </summary>
    1510              : /// <param name="pll">PLL to reset</param>
    1511              : /// <param name="interval">Polling interval, in microseconds</param>
    1512            0 : void DTCLib::DTC_Registers::ResetSERDESPLL(const DTC_PLL_ID& pll, int interval)
    1513              : {
    1514            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1515            0 :         data[pll + 8] = 1;
    1516            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1517              : 
    1518            0 :         usleep(interval);
    1519              : 
    1520            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1521            0 :         data[pll + 8] = 0;
    1522            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1523            0 : }
    1524              : 
    1525              : /// <summary>
    1526              : /// Read if a SERDES PLL reset is currently in progress
    1527              : /// </summary>
    1528              : /// <param name="pll">PLL to read</param>
    1529              : /// <returns>True if a SERDES reset is in progress</returns>
    1530            0 : bool DTCLib::DTC_Registers::ReadResetSERDESPLL(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
    1531              : {
    1532            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1533            0 :         return dataSet[pll + 8];
    1534              : }
    1535              : 
    1536              : /// <summary>
    1537              : /// Reset the SERDES
    1538              : /// Will poll the Reset SERDES Done flag until the SERDES reset is complete
    1539              : /// </summary>
    1540              : /// <param name="link">Link to reset</param>
    1541              : /// <param name="interval">Polling interval, in microseconds</param>
    1542            0 : void DTCLib::DTC_Registers::ResetSERDES(DTC_Link_ID const& link, int interval)
    1543              : {
    1544            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES Reset Loop for Link " << link;
    1545            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1546            0 :         if (link == DTC_Link_ALL)
    1547              :         {
    1548            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1549            0 :                         data[i] = 1;
    1550              :         }
    1551              :         else
    1552            0 :                 data[link] = 1;
    1553            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1554              : 
    1555              :         // usleep(interval);
    1556              : 
    1557            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1558            0 :         if (link == DTC_Link_ALL)
    1559              :         {
    1560            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1561            0 :                         data[i] = 0;
    1562              :         }
    1563              :         else
    1564            0 :                 data[link] = 0;
    1565            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1566              : 
    1567            0 :         auto resetDone = false;
    1568            0 :         uint32_t loops = 0;
    1569            0 :         while (!resetDone && ++loops < 100)
    1570              :         {
    1571            0 :                 usleep(interval);
    1572              : 
    1573            0 :                 if (link == DTC_Link_ALL)
    1574              :                 {
    1575              :                         // Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1576              :                         //       For new DTC versions since December 2023, EVB is not instantiated, so also ignore
    1577              :                         //  resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
    1578              :                         //  resetDone = resetDone &&
    1579              :                         //      ( ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF);
    1580            0 :                         resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0x3F) == 0x3F;
    1581            0 :                         resetDone = resetDone &&
    1582            0 :                                                 (((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0x3F) == 0x3F);
    1583              :                 }
    1584              :                 else
    1585              :                 {
    1586            0 :                         resetDone = ReadResetRXSERDESDone(link);
    1587            0 :                         resetDone = resetDone && ReadResetTXSERDESDone(link);
    1588              :                 }
    1589            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1590              :         }
    1591              : 
    1592            0 :         if (loops >= 100)
    1593              :         {
    1594            0 :                 __SS__ << "Timeout waiting for SERDES Reset loop=" << loops;
    1595            0 :                 __SS_THROW__;
    1596              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES Reset loop.");
    1597            0 :         }
    1598            0 : }
    1599              : 
    1600            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDiagFifo(DTC_Link_ID const& link)
    1601              : {
    1602            0 :         __COUT__ << "FormatRXDiagFifo.";
    1603              :         DTC_Register reg;
    1604            0 :         switch (link)
    1605              :         {
    1606            0 :                 case DTC_Link_0:
    1607            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link0;
    1608            0 :                         break;
    1609            0 :                 case DTC_Link_1:
    1610            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link1;
    1611            0 :                         break;
    1612            0 :                 case DTC_Link_2:
    1613            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link2;
    1614            0 :                         break;
    1615            0 :                 case DTC_Link_3:
    1616            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link3;
    1617            0 :                         break;
    1618            0 :                 case DTC_Link_4:
    1619            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link4;
    1620            0 :                         break;
    1621            0 :                 case DTC_Link_5:
    1622            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link5;
    1623            0 :                         break;
    1624            0 :                 case DTC_Link_CFO:
    1625            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_LinkCFO;
    1626            0 :                         break;
    1627            0 :                 default: {
    1628            0 :                         __SS__ << "Invalid DTC Link";
    1629            0 :                         __SS_THROW__;
    1630              :                         // throw std::runtime_error("Invalid DTC Link");
    1631            0 :                 }
    1632              :         }
    1633              : 
    1634            0 :         auto form = CreateFormatter(reg);
    1635            0 :         form.description = "Rx Diag FIFO";
    1636            0 :         form.vals.push_back("");  // translation
    1637            0 :         for (uint8_t i = 0; i < 100; ++i)
    1638              :         {
    1639            0 :                 __COUT__ << "FormatRXDiagFifo loop." << i;
    1640            0 :                 std::ostringstream o;
    1641            0 :                 o << std::hex << std::setfill('0');
    1642            0 :                 o << "    0x" << std::setw(4) << static_cast<int>(form.address) << "  | 0x" << std::setw(8)
    1643            0 :                   << static_cast<int>(ReadRegister_(reg)) << " | ";
    1644            0 :                 form.vals.push_back(o.str());
    1645            0 :         }
    1646              : 
    1647            0 :         __COUT__ << "FormatRXDiagFifo loop done.";
    1648            0 :         return form;
    1649            0 : }
    1650              : 
    1651            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDiagFifo(DTC_Link_ID const& link)
    1652              : {
    1653              :         DTC_Register reg;
    1654            0 :         switch (link)
    1655              :         {
    1656            0 :                 case DTC_Link_0:
    1657            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link0;
    1658            0 :                         break;
    1659            0 :                 case DTC_Link_1:
    1660            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link1;
    1661            0 :                         break;
    1662            0 :                 case DTC_Link_2:
    1663            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link2;
    1664            0 :                         break;
    1665            0 :                 case DTC_Link_3:
    1666            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link3;
    1667            0 :                         break;
    1668            0 :                 case DTC_Link_4:
    1669            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link4;
    1670            0 :                         break;
    1671            0 :                 case DTC_Link_5:
    1672            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link5;
    1673            0 :                         break;
    1674            0 :                 case DTC_Link_CFO:
    1675            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_LinkCFO;
    1676            0 :                         break;
    1677            0 :                 default: {
    1678            0 :                         __SS__ << "Invalid DTC Link";
    1679            0 :                         __SS_THROW__;
    1680              :                         // throw std::runtime_error("Invalid DTC Link");
    1681            0 :                 }
    1682              :         }
    1683            0 :         auto form = CreateFormatter(reg);
    1684            0 :         form.description = "Tx Diag FIFO";
    1685            0 :         form.vals.push_back("");  // translation
    1686            0 :         for (uint8_t i = 0; i < 100; ++i)
    1687              :         {
    1688            0 :                 std::ostringstream o;
    1689            0 :                 o << std::hex << std::setfill('0');
    1690            0 :                 o << "    0x" << std::setw(4) << static_cast<int>(form.address) << "  | 0x" << std::setw(8)
    1691            0 :                   << static_cast<int>(ReadRegister_(reg)) << " | ";
    1692            0 :                 form.vals.push_back(o.str());
    1693            0 :         }
    1694              : 
    1695            0 :         return form;
    1696            0 : }
    1697              : 
    1698              : /// <summary>
    1699              : /// Read if a SERDES reset is currently in progress
    1700              : /// </summary>
    1701              : /// <param name="link">Link to read</param>
    1702              : /// <returns>True if a SERDES reset is in progress</returns>
    1703            0 : bool DTCLib::DTC_Registers::ReadResetSERDES(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1704              : {
    1705            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1706            0 :         return dataSet[link];
    1707              : }
    1708              : 
    1709              : /// <summary>
    1710              : /// Formats the register's current value for register dumps
    1711              : /// </summary>
    1712              : /// <returns>RegisterFormatter object containing register information</returns>
    1713            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESReset()
    1714              : {
    1715            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_Reset);
    1716            0 :         form.description = "SERDES Reset";
    1717            0 :         form.vals.push_back("           ([TX,RX,Link])");
    1718            0 :         for (auto r : DTC_ROC_Links)
    1719            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ":     [" +
    1720            0 :                                                         (ReadResetSERDESTX(r, form.value) ? "x" : ".") +
    1721            0 :                                                         (ReadResetSERDESRX(r, form.value) ? "x" : ".") +
    1722            0 :                                                         (ReadResetSERDES(r, form.value) ? "x" : ".") + "]");
    1723            0 :         form.vals.push_back(std::string("CFO:        [") +
    1724            0 :                                                 (ReadResetSERDESTX(DTC_Link_CFO, form.value) ? "x" : ".") +
    1725            0 :                                                 (ReadResetSERDESRX(DTC_Link_CFO, form.value) ? "x" : ".") +
    1726            0 :                                                 (ReadResetSERDES(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
    1727            0 :         form.vals.push_back(std::string("EVB:        [") +
    1728            0 :                                                 (ReadResetSERDESTX(DTC_Link_EVB, form.value) ? "x" : ".") +
    1729            0 :                                                 (ReadResetSERDESRX(DTC_Link_EVB, form.value) ? "x" : ".") +
    1730            0 :                                                 (ReadResetSERDES(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
    1731              : 
    1732            0 :         form.vals.push_back("           ([ x = 1 (hi) ])");
    1733            0 :         for (auto r : DTC_PLLs)
    1734            0 :                 form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ": [" +
    1735            0 :                                                         (ReadResetSERDESPLL(r, form.value) ? "x" : ".") + "]");
    1736            0 :         form.vals.push_back(std::string("PLL CFO RX: [") +
    1737            0 :                                                 (ReadResetSERDESPLL(DTC_PLL_CFO_RX, form.value) ? "x" : ".") + "]");
    1738            0 :         form.vals.push_back(std::string("PLL CFO TX: [") +
    1739            0 :                                                 (ReadResetSERDESPLL(DTC_PLL_CFO_TX, form.value) ? "x" : ".") + "]");
    1740              : 
    1741            0 :         return form;
    1742            0 : }
    1743              : 
    1744              : // SERDES RX Disparity Error Register
    1745              : /// <summary>
    1746              : /// Read the SERDES RX Dispatity Error bits
    1747              : /// </summary>
    1748              : /// <param name="link">Link to read</param>
    1749              : /// <returns>DTC_SERDESRXDisparityError object with error bits</returns>
    1750            0 : DTCLib::DTC_SERDESRXDisparityError DTCLib::DTC_Registers::ReadSERDESRXDisparityError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1751              : {
    1752            0 :         return DTC_SERDESRXDisparityError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXDisparityError), link);
    1753              : }
    1754              : 
    1755              : /// <summary>
    1756              : /// Formats the register's current value for register dumps
    1757              : /// </summary>
    1758              : /// <returns>RegisterFormatter object containing register information</returns>
    1759            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityError()
    1760              : {
    1761            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXDisparityError);
    1762            0 :         form.description = "SERDES RX Disparity Error";
    1763            0 :         form.vals.push_back("       ([H,L])");
    1764            0 :         for (auto r : DTC_ROC_Links)
    1765              :         {
    1766            0 :                 auto re = ReadSERDESRXDisparityError(r, form.value);
    1767            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
    1768            0 :                                                         to_string(re.GetData()[0]) + "]");
    1769              :         }
    1770            0 :         auto ce = ReadSERDESRXDisparityError(DTC_Link_CFO, form.value);
    1771            0 :         form.vals.push_back(std::string("CFO:    [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
    1772            0 :         return form;
    1773            0 : }
    1774              : 
    1775              : // SERDES RX Character Not In Table Error Register
    1776              : /// <summary>
    1777              : /// Read the SERDES Character Not In Table Error bits
    1778              : /// </summary>
    1779              : /// <param name="link">Link to read</param>
    1780              : /// <returns>DTC_CharacterNotInTableError object with error bits</returns>
    1781            0 : DTCLib::DTC_CharacterNotInTableError DTCLib::DTC_Registers::ReadSERDESRXCharacterNotInTableError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1782              : {
    1783            0 :         return DTC_CharacterNotInTableError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXCharacterNotInTableError), link);
    1784              : }
    1785              : 
    1786              : /// <summary>
    1787              : /// Formats the register's current value for register dumps
    1788              : /// </summary>
    1789              : /// <returns>RegisterFormatter object containing register information</returns>
    1790            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCharacterNotInTableError()
    1791              : {
    1792            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXCharacterNotInTableError);
    1793            0 :         form.description = "SERDES RX CNIT Error";
    1794            0 :         form.vals.push_back("       ([H,L])");
    1795            0 :         for (auto r : DTC_ROC_Links)
    1796              :         {
    1797            0 :                 auto re = ReadSERDESRXCharacterNotInTableError(r, form.value);
    1798            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
    1799            0 :                                                         to_string(re.GetData()[0]) + "]");
    1800              :         }
    1801            0 :         auto ce = ReadSERDESRXCharacterNotInTableError(DTC_Link_CFO, form.value);
    1802            0 :         form.vals.push_back(std::string("CFO:    [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
    1803            0 :         return form;
    1804            0 : }
    1805              : 
    1806              : // SERDES Unlock Error Register
    1807              : /// <summary>
    1808              : /// Read whether the SERDES CDR Unlock Error bit is set
    1809              : /// </summary>
    1810              : /// <param name="link">Link to check</param>
    1811              : /// <returns>True if the SERDES CDR Unlock Error bit is set on the given link</returns>
    1812            0 : bool DTCLib::DTC_Registers::ReadSERDESCDRUnlockError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1813              : {
    1814            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
    1815            0 :         return dataSet[16 + link];
    1816              : }
    1817              : 
    1818              : /// <summary>
    1819              : /// Read whether the SERDES PLL Unlock Error bit is set
    1820              : /// </summary>
    1821              : /// <param name="pll">PLL to check</param>
    1822              : /// <returns>True if the SERDES PLL Unlock Error bit is set for the given PLL</returns>
    1823            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLUnlockError(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
    1824              : {
    1825            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
    1826            0 :         return dataSet[pll];
    1827              : }
    1828              : 
    1829              : /// <summary>
    1830              : /// Formats the register's current value for register dumps
    1831              : /// </summary>
    1832              : /// <returns>RegisterFormatter object containing register information</returns>
    1833            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESUnlockError()
    1834              : {
    1835            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_UnlockError);
    1836            0 :         form.description = "SERDES Unlock Error";
    1837            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1838            0 :         for (auto r : DTC_ROC_Links)
    1839            0 :                 form.vals.push_back(std::string("CDR Link ") + std::to_string(r) + ":    [" +
    1840            0 :                                                         (ReadSERDESCDRUnlockError(r, form.value) ? "x" : " ") + "]");
    1841            0 :         form.vals.push_back(std::string("CDR CFO:       [") + (ReadSERDESCDRUnlockError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1842            0 :         form.vals.push_back(std::string("CDR EVB:       [") + (ReadSERDESCDRUnlockError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1843            0 :         for (auto r : DTC_PLLs)
    1844            0 :                 form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ":    [" +
    1845            0 :                                                         (ReadSERDESPLLUnlockError(r, form.value) ? "x" : " ") + "]");
    1846            0 :         form.vals.push_back(std::string("PLL CFO RX:    [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_RX, form.value) ? "x" : " ") + "]");
    1847            0 :         form.vals.push_back(std::string("PLL CFO TX:    [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_TX, form.value) ? "x" : " ") + "]");
    1848            0 :         form.vals.push_back(std::string("PLL EVB:       [") + (ReadSERDESPLLUnlockError(DTC_PLL_EVB_TXRX, form.value) ? "x" : " ") + "]");
    1849            0 :         form.vals.push_back(std::string("PLL PunchClock:[") + (ReadSERDESPLLUnlockError(DTC_PLL_PunchedClock, form.value) ? "x" : " ") + "]");
    1850            0 :         return form;
    1851            0 : }
    1852              : 
    1853              : // SERDES PLL Locked Register
    1854              : /// <summary>
    1855              : /// Read if the SERDES PLL is locked for the given SERDES link
    1856              : /// </summary>
    1857              : /// <param name="link">Link to read</param>
    1858              : /// <returns>True if the PLL is locked, false otherwise</returns>
    1859            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLLocked(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1860              : {
    1861            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLLocked);
    1862            0 :         return dataSet[link];
    1863              : }
    1864              : 
    1865              : /// <summary>
    1866              : /// Formats the register's current value for register dumps
    1867              : /// </summary>
    1868              : /// <returns>RegisterFormatter object containing register information</returns>
    1869            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLLocked()
    1870              : {
    1871            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLLocked);
    1872            0 :         form.description = "SERDES PLL Locked";
    1873            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1874            0 :         for (auto r : DTC_ROC_Links)
    1875            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ":         [" + (ReadSERDESPLLLocked(r, form.value) ? "x" : " ") + "]");
    1876            0 :         form.vals.push_back(std::string("CFO:            [") + (ReadSERDESPLLLocked(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1877            0 :         form.vals.push_back(std::string("EVB:            [") + (ReadSERDESPLLLocked(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1878            0 :         form.vals.push_back(std::string("Clock to JA:    [") + ((((form.value) >> 8) & 1) ? "x" : " ") + "]");
    1879            0 :         form.vals.push_back(std::string("Clock from JA:  [") + ((((form.value) >> 9) & 1) ? "x" : " ") + "]");
    1880            0 :         return form;
    1881            0 : }
    1882              : 
    1883              : /// <summary>
    1884              : /// Disable the SERDES PLL Power Down bit for the given link, enabling that link
    1885              : /// </summary>
    1886              : /// <param name="link">Link to set</param>
    1887            0 : void DTCLib::DTC_Registers::EnableSERDESPLL(DTC_Link_ID const& link)
    1888              : {
    1889            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1890            0 :         data[link] = 0;
    1891            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
    1892            0 : }
    1893              : 
    1894              : /// <summary>
    1895              : /// Enable the SERDES PLL Power Down bit for the given link, disabling that link
    1896              : /// </summary>
    1897              : /// <param name="link">Link to set</param>
    1898            0 : void DTCLib::DTC_Registers::DisableSERDESPLL(DTC_Link_ID const& link)
    1899              : {
    1900            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1901            0 :         data[link] = 1;
    1902            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
    1903            0 : }
    1904              : 
    1905              : /// <summary>
    1906              : /// Read the SERDES PLL Power Down bit for the given link
    1907              : /// </summary>
    1908              : /// <param name="link">link to read</param>
    1909              : /// <returns>Value of the bit</returns>
    1910            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLPowerDown(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1911              : {
    1912            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1913            0 :         return data[link];
    1914              : }
    1915              : 
    1916              : /// <summary>
    1917              : /// Formats the register's current value for register dumps
    1918              : /// </summary>
    1919              : /// <returns>RegisterFormatter object containing register information</returns>
    1920            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLPowerDown()
    1921              : {
    1922            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLPowerDown);
    1923            0 :         form.description = "SERDES PLL Power Down";
    1924            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1925            0 :         for (auto r : DTC_ROC_Links)
    1926            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (ReadSERDESPLLPowerDown(r, form.value) ? "x" : " ") + "]");
    1927            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadSERDESPLLPowerDown(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1928            0 :         form.vals.push_back(std::string("EVB:    [") + (ReadSERDESPLLPowerDown(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1929            0 :         return form;
    1930            0 : }
    1931              : 
    1932              : // SERDES RX Status Register
    1933              : /// <summary>
    1934              : /// Read the SERDES RX Status for the given SERDES Link
    1935              : /// </summary>
    1936              : /// <param name="link">Link to read</param>
    1937              : /// <returns>DTC_RXStatus object</returns>
    1938            0 : DTCLib::DTC_RXStatus DTCLib::DTC_Registers::ReadSERDESRXStatus(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1939              : {
    1940            0 :         std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXStatus)) >> 3 * link;
    1941            0 :         return static_cast<DTC_RXStatus>(dataSet.to_ulong());
    1942              : }
    1943              : 
    1944              : /// <summary>
    1945              : /// Formats the register's current value for register dumps
    1946              : /// </summary>
    1947              : /// <returns>RegisterFormatter object containing register information</returns>
    1948            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXStatus()
    1949              : {
    1950            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXStatus);
    1951            0 :         form.description = "SERDES RX Status";
    1952            0 :         form.vals.push_back("");  // translation
    1953            0 :         for (auto r : DTC_ROC_Links)
    1954              :         {
    1955            0 :                 auto re = ReadSERDESRXStatus(r, form.value);
    1956            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " + DTC_RXStatusConverter(re).toString());
    1957              :         }
    1958            0 :         auto ce = ReadSERDESRXStatus(DTC_Link_CFO, form.value);
    1959            0 :         form.vals.push_back(std::string("CFO:    ") + DTC_RXStatusConverter(ce).toString());
    1960              : 
    1961            0 :         return form;
    1962            0 : }
    1963              : 
    1964              : // SERDES Reset Done Register
    1965              : /// <summary>
    1966              : /// Read the SERDES Reset RX FSM Done bit
    1967              : /// </summary>
    1968              : /// <param name="link">link to read</param>
    1969              : /// <returns>Value of the bit</returns>
    1970            0 : bool DTCLib::DTC_Registers::ReadResetRXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1971              : {
    1972            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1973            0 :         return dataSet[link + 24];
    1974              : }
    1975              : /// <summary>
    1976              : /// Read the SERDES Reset RX Done bit
    1977              : /// </summary>
    1978              : /// <param name="link">link to read</param>
    1979              : /// <returns>Value of the bit</returns>
    1980            0 : bool DTCLib::DTC_Registers::ReadResetRXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1981              : {
    1982            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1983            0 :         return dataSet[link + 16];
    1984              : }
    1985              : /// <summary>
    1986              : /// Read the SERDES Reset TX FSM Done bit
    1987              : /// </summary>
    1988              : /// <param name="link">link to read</param>
    1989              : /// <returns>Value of the bit</returns>
    1990            0 : bool DTCLib::DTC_Registers::ReadResetTXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1991              : {
    1992            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1993            0 :         return dataSet[link + 8];
    1994              : }
    1995              : /// <summary>
    1996              : /// Read the SERDES Reset TX Done bit
    1997              : /// </summary>
    1998              : /// <param name="link">link to read</param>
    1999              : /// <returns>Value of the bit</returns>
    2000            0 : bool DTCLib::DTC_Registers::ReadResetTXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2001              : {
    2002            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    2003            0 :         return dataSet[link];
    2004              : }
    2005              : 
    2006              : /// <summary>
    2007              : /// Formats the register's current value for register dumps
    2008              : /// </summary>
    2009              : /// <returns>RegisterFormatter object containing register information</returns>
    2010            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESResetDone()
    2011              : {
    2012            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_ResetDone);
    2013            0 :         form.description = "SERDES Reset Done";
    2014            0 :         form.vals.push_back("       ([RX FSM, RX, TX FSM, TX])");
    2015            0 :         for (auto r : DTC_ROC_Links)
    2016            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2017            0 :                                                         (ReadResetRXFSMSERDESDone(r, form.value) ? "x" : ".") +
    2018            0 :                                                         (ReadResetRXSERDESDone(r, form.value) ? "x" : ".") +
    2019            0 :                                                         (ReadResetTXFSMSERDESDone(r, form.value) ? "x" : ".") +
    2020            0 :                                                         (ReadResetTXSERDESDone(r, form.value) ? "x" : ".") + "]");
    2021            0 :         form.vals.push_back(std::string("CFO:    [") +
    2022            0 :                                                 (ReadResetRXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2023            0 :                                                 (ReadResetRXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2024            0 :                                                 (ReadResetTXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2025            0 :                                                 (ReadResetTXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
    2026            0 :         form.vals.push_back(std::string("EVB:    [") +
    2027            0 :                                                 (ReadResetRXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2028            0 :                                                 (ReadResetRXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2029            0 :                                                 (ReadResetTXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2030            0 :                                                 (ReadResetTXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
    2031            0 :         return form;
    2032            0 : }
    2033              : 
    2034              : // SFP / SERDES Status Register
    2035              : 
    2036              : /// <summary>
    2037              : /// Read the SERDES CDR Lock bit for the given SERDES Link
    2038              : /// </summary>
    2039              : /// <param name="link">Link to read</param>
    2040              : /// <returns>True if the SERDES CDR Lock bit is set</returns>
    2041            0 : bool DTCLib::DTC_Registers::ReadSERDESRXCDRLock(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2042              : {
    2043            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
    2044              : 
    2045              :         // read the lock value 20x because it might not be stable, consider unlocked if ever low
    2046            0 :         if (!val.has_value() && dataSet[link])
    2047              :         {
    2048            0 :                 for (int i = 0; i < 20; ++i)
    2049              :                 {
    2050            0 :                         std::bitset<32> tmpDataSet = ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
    2051            0 :                         if (!tmpDataSet[link])  // override with any exception
    2052            0 :                                 return false;
    2053            0 :                         usleep(10);
    2054              :                 }
    2055              :         }
    2056            0 :         return dataSet[link];
    2057              : }
    2058              : 
    2059              : /// <summary>
    2060              : /// Formats the register's current value for register dumps
    2061              : /// </summary>
    2062              : /// <returns>RegisterFormatter object containing register information</returns>
    2063            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRLockStatus()
    2064              : {
    2065            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCDRLockStatus);
    2066            0 :         form.description = "RX CDR Lock Status";
    2067            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    2068            0 :         for (auto r : DTC_ROC_Links)
    2069              :         {
    2070            0 :                 form.vals.push_back(std::string("ROC Link ") + std::to_string(r) +
    2071            0 :                                                         " CDR Lock:   [" + (ReadSERDESRXCDRLock(r) ? "x" : " ") + "]");  // do not use form.value to force multi reread in case of instability
    2072              :         }
    2073            0 :         if (ReadCFOEmulationMode())
    2074            0 :                 form.vals.push_back(std::string("CFO Emulated CDR Lock: [") + (ReadSERDESRXCDRLock(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    2075              :         else
    2076            0 :                 form.vals.push_back(std::string("CFO CDR Lock:          [") + (ReadSERDESRXCDRLock(DTC_Link_CFO) ? "x" : " ") + "]");  // do not use form.value to force multi reread in case of instability
    2077              : 
    2078            0 :         form.vals.push_back(std::string("EVB CDR Lock:          [") + (ReadSERDESRXCDRLock(DTC_Link_EVB) ? "x" : " ") + "]");  // do not use form.value to force multi reread in case of instability
    2079            0 :         return form;
    2080            0 : }
    2081              : 
    2082              : // DMA Timeout Preset Register
    2083              : /// <summary>
    2084              : /// Set the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
    2085              : /// The default value is 0x800
    2086              : /// </summary>
    2087              : /// <param name="preset">Maximum active time for DMA buffers</param>
    2088            0 : void DTCLib::DTC_Registers::SetDMATimeoutPreset(uint32_t preset)
    2089              : {
    2090            0 :         WriteRegister_(preset, DTC_Register_DMATimeoutPreset);
    2091            0 : }
    2092              : 
    2093              : /// <summary>
    2094              : /// Read the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
    2095              : /// The default value is 0x800
    2096              : /// </summary>
    2097              : /// <returns>Maximum active time for DMA buffers</returns>
    2098            0 : uint32_t DTCLib::DTC_Registers::ReadDMATimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_DMATimeoutPreset); }
    2099              : 
    2100              : /// <summary>
    2101              : /// Formats the register's current value for register dumps
    2102              : /// </summary>
    2103              : /// <returns>RegisterFormatter object containing register information</returns>
    2104            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATimeoutPreset()
    2105              : {
    2106            0 :         auto form = CreateFormatter(DTC_Register_DMATimeoutPreset);
    2107            0 :         form.description = "DMA Timeout";
    2108            0 :         std::stringstream o;
    2109            0 :         o << "0x" << std::hex << ReadDMATimeoutPreset(form.value);
    2110            0 :         form.vals.push_back(o.str());
    2111            0 :         return form;
    2112            0 : }
    2113              : 
    2114              : // ROC Timeout Preset Register
    2115              : /// <summary>
    2116              : /// Read the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
    2117              : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
    2118              : /// </summary>
    2119              : /// <returns>Timeout value</returns>
    2120            0 : uint32_t DTCLib::DTC_Registers::ReadROCTimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeout); }
    2121              : 
    2122              : /// <summary>
    2123              : /// Set the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
    2124              : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
    2125              : /// </summary>
    2126              : /// <param name="preset">Timeout value. Default: 0x200000</param>
    2127            0 : void DTCLib::DTC_Registers::SetROCTimeoutPreset(uint32_t preset)
    2128              : {
    2129            0 :         WriteRegister_(preset, DTC_Register_ROCReplyTimeout);
    2130            0 : }
    2131              : 
    2132              : /// <summary>
    2133              : /// Formats the register's current value for register dumps
    2134              : /// </summary>
    2135              : /// <returns>RegisterFormatter object containing register information</returns>
    2136            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeout()
    2137              : {
    2138            0 :         auto form = CreateFormatter(DTC_Register_ROCReplyTimeout);
    2139            0 :         form.description = "ROC Reply Timeout";
    2140            0 :         std::stringstream o;
    2141            0 :         o << "0x" << std::hex << ReadROCTimeoutPreset(form.value);
    2142            0 :         form.vals.push_back(o.str());
    2143            0 :         return form;
    2144            0 : }
    2145              : 
    2146              : // ROC Timeout Error Register
    2147              : /// <summary>
    2148              : /// Clear the ROC Data Packet timeout error flag for the given SERDES link
    2149              : /// </summary>
    2150              : /// <param name="link">Link to clear</param>
    2151            0 : bool DTCLib::DTC_Registers::ReadROCTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2152              : {
    2153            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeoutError);
    2154            0 :         return data[static_cast<int>(link)];
    2155              : }
    2156              : 
    2157              : /// <summary>
    2158              : /// Read the ROC Data Packet Timeout Error Flag for the given SERDES link
    2159              : /// </summary>
    2160              : /// <param name="link">Link to read</param>
    2161              : /// <returns>True if the error flag is set, false otherwise</returns>
    2162            0 : void DTCLib::DTC_Registers::ClearROCTimeoutError(DTC_Link_ID const& link)
    2163              : {
    2164            0 :         std::bitset<32> data = 0x0;
    2165            0 :         data[link] = 1;
    2166            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ROCReplyTimeoutError);
    2167            0 : }
    2168              : 
    2169              : /// <summary>
    2170              : /// Formats the register's current value for register dumps
    2171              : /// </summary>
    2172              : /// <returns>RegisterFormatter object containing register information</returns>
    2173            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeoutError()
    2174              : {
    2175            0 :         auto form = CreateFormatter(DTC_Register_ROCReplyTimeoutError);
    2176            0 :         form.description = "ROC Reply Timeout Error";
    2177            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    2178            0 :         for (auto r : DTC_ROC_Links)
    2179              :         {
    2180            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2181            0 :                                                         (ReadROCTimeoutError(r, form.value) ? "x" : " ") + "]");
    2182              :         }
    2183            0 :         return form;
    2184            0 : }
    2185              : 
    2186              : /// <summary>
    2187              : /// Set the DTC ID and EVB Info register
    2188              : /// </summary>
    2189              : /// <returns></returns>
    2190            0 : void DTCLib::DTC_Registers::SetEVBInfo(uint8_t dtcid, uint8_t mode,
    2191              :                                                                            uint8_t partitionId, uint8_t macByte)
    2192              : {
    2193            0 :         uint32_t regVal = dtcid << 24;
    2194            0 :         regVal |= mode << 16;
    2195            0 :         regVal |= partitionId << 8;
    2196            0 :         regVal |= macByte;
    2197            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2198            0 : }
    2199              : 
    2200              : /// <summary>
    2201              : /// Set only the DTC ID within the EVB Info register
    2202              : /// </summary>
    2203              : /// <returns></returns>
    2204            0 : void DTCLib::DTC_Registers::SetDTCID(uint8_t dtcid)
    2205              : {
    2206            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0x00FFFFFF;
    2207            0 :         regVal += dtcid << 24;
    2208            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2209            0 : }
    2210              : 
    2211              : // EVB Network Partition ID / EVB Network Local MAC Index Register
    2212            0 : uint8_t DTCLib::DTC_Registers::ReadDTCID(std::optional<uint32_t> val)
    2213              : {
    2214            0 :         auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF000000;
    2215            0 :         return static_cast<uint8_t>(regVal >> 24);
    2216              : }
    2217              : 
    2218              : /// <summary>
    2219              : /// Set the EVB Mode byte
    2220              : /// </summary>
    2221              : /// <param name="mode">New Mode byte</param>
    2222            0 : void DTCLib::DTC_Registers::SetEVBMode(uint8_t mode)
    2223              : {
    2224            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFF00FFFF;
    2225            0 :         regVal += mode << 16;
    2226            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2227            0 : }
    2228              : 
    2229              : /// <summary>
    2230              : /// Read the EVB Mode byte
    2231              : /// </summary>
    2232              : /// <returns>EVB Mode byte</returns>
    2233            0 : uint8_t DTCLib::DTC_Registers::ReadEVBMode(std::optional<uint32_t> val)
    2234              : {
    2235            0 :         auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF0000;
    2236            0 :         return static_cast<uint8_t>(regVal >> 16);
    2237              : }
    2238              : 
    2239              : /// <summary>
    2240              : /// Set the local partition ID
    2241              : /// </summary>
    2242              : /// <param name="id">Local partition ID</param>
    2243            0 : void DTCLib::DTC_Registers::SetEVBLocalParitionID(uint8_t partitionId)
    2244              : {
    2245            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFF00FF;
    2246            0 :         regVal += partitionId << 8;
    2247            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2248            0 : }
    2249              : 
    2250              : /// <summary>
    2251              : /// Read the local partition ID
    2252              : /// </summary>
    2253              : /// <returns>Partition ID</returns>
    2254            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalParitionID(std::optional<uint32_t> val)
    2255              : {
    2256            0 :         return static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) >> 8) & 0xFF);
    2257              : }
    2258              : 
    2259              : /// <summary>
    2260              : /// Set the MAC address for the EVB network (lowest byte)
    2261              : /// </summary>
    2262              : /// <param name="macByte">MAC Address</param>
    2263            0 : void DTCLib::DTC_Registers::SetEVBLocalMACAddress(uint8_t macByte)
    2264              : {
    2265            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFFFF00;
    2266            0 :         regVal += macByte;
    2267            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2268            0 : }
    2269              : 
    2270              : /// <summary>
    2271              : /// Read the MAC address for the EVB network (lowest byte)
    2272              : /// </summary>
    2273              : /// <returns>MAC Address</returns>
    2274            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalMACAddress(std::optional<uint32_t> val) { return (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF; }
    2275              : 
    2276              : /// <summary>
    2277              : /// Formats the register's current value for register dumps
    2278              : /// </summary>
    2279              : /// <returns>RegisterFormatter object containing register information</returns>
    2280            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBLocalParitionIDMACIndex()
    2281              : {
    2282            0 :         auto form = CreateFormatter(DTC_Register_EVBPartitionID);
    2283            0 :         form.description = "EVB Local Partition ID / MAC Index";
    2284            0 :         form.vals.push_back("");  // translation
    2285            0 :         std::ostringstream o;
    2286            0 :         o << "DTC ID:                         0x" << std::hex << static_cast<int>(ReadDTCID(form.value));
    2287            0 :         form.vals.push_back(o.str());
    2288            0 :         o.str("");
    2289            0 :         o.clear();
    2290            0 :         o << "EVB Mode:                       0x" << std::hex << static_cast<int>(ReadEVBMode(form.value));
    2291            0 :         form.vals.push_back(o.str());
    2292            0 :         o.str("");
    2293            0 :         o.clear();
    2294            0 :         o << "EVB Parition ID:                0x" << std::hex << static_cast<int>(ReadEVBLocalParitionID(form.value));
    2295            0 :         form.vals.push_back(o.str());
    2296            0 :         o.str("");
    2297            0 :         o.clear();
    2298            0 :         auto mac = static_cast<int>(ReadEVBLocalMACAddress(form.value));
    2299            0 :         o << "EVB Self MAC Address Last Byte: 0x" << std::hex << mac << " (" << std::dec << mac << ")";
    2300            0 :         form.vals.push_back(o.str());
    2301            0 :         return form;
    2302            0 : }
    2303              : 
    2304              : /// EVB Number of Destination Nodes Register
    2305            0 : void DTCLib::DTC_Registers::SetEVBClusterInfo(uint16_t deadTime,
    2306              :                                                                                           uint8_t baseDTCAddress, uint8_t numOfDTCs)
    2307              : {
    2308            0 :         uint32_t regVal = (deadTime & 0xFFFF) << 16;
    2309            0 :         regVal |= baseDTCAddress << 8;
    2310            0 :         regVal |= numOfDTCs;
    2311            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2312            0 : }
    2313              : 
    2314              : /// <summary>
    2315              : /// Set the dead time (clocks at start of destination switch to block tx to avoid collissions with previous round-robin tx) of the EVB cluster
    2316              : /// </summary>
    2317            0 : void DTCLib::DTC_Registers::SetEVBDeadTime(uint16_t deadTime)
    2318              : {
    2319            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0x0FFFF;
    2320            0 :         regVal += (deadTime & 0xFFFF) << 16;
    2321            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2322            0 : }
    2323              : 
    2324              : /// <summary>
    2325              : /// Read the dead time (clocks at start of destination switch to block tx to avoid collissions with previous round-robin tx) of the EVB cluster
    2326              : /// </summary>
    2327            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDeadTime(std::optional<uint32_t> val)
    2328              : {
    2329            0 :         return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFFFF0000)) >> 16);
    2330              : }
    2331              : 
    2332              : /// <summary>
    2333              : /// Set the start node in the EVB cluster
    2334              : /// </summary>
    2335            0 : void DTCLib::DTC_Registers::SetEVBStartNode(uint8_t startNode)
    2336              : {
    2337            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFF00FF;
    2338            0 :         regVal += startNode << 8;
    2339            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2340            0 : }
    2341              : 
    2342              : /// <summary>
    2343              : /// Read the start node in the EVB cluster
    2344              : /// </summary>
    2345            0 : uint8_t DTCLib::DTC_Registers::ReadEVBStartNode(std::optional<uint32_t> val)
    2346              : {
    2347            0 :         return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFF00)) >> 8);
    2348              : }
    2349              : 
    2350              : /// <summary>
    2351              : /// Set the number of destination nodes in the EVB cluster
    2352              : /// </summary>
    2353              : /// <param name="numOfNodes">Number of nodes</param>
    2354            0 : void DTCLib::DTC_Registers::SetEVBNumberOfDestinationNodes(uint8_t numOfNodes)
    2355              : {
    2356            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFFFF00;
    2357            0 :         regVal += numOfNodes;
    2358            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2359            0 : }
    2360              : 
    2361              : /// <summary>
    2362              : /// Read the number of destination nodes in the EVB cluster
    2363              : /// </summary>
    2364              : /// <returns>Number of nodes</returns>
    2365            0 : uint8_t DTCLib::DTC_Registers::ReadEVBNumberOfDestinationNodes(std::optional<uint32_t> val)
    2366              : {
    2367            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFF);
    2368              : }
    2369              : 
    2370              : /// <summary>
    2371              : /// Formats the register's current value for register dumps
    2372              : /// </summary>
    2373              : /// <returns>RegisterFormatter object containing register information</returns>
    2374            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBClusterInfo()
    2375              : {
    2376            0 :         auto form = CreateFormatter(DTC_Register_EVBConfiguration);
    2377            0 :         form.description = "EVB DTC Cluster Configuration";
    2378            0 :         form.vals.push_back("");  // translation
    2379            0 :         std::stringstream o;
    2380            0 :         o << "EVB Dead Time: " << std::dec << static_cast<int>(ReadEVBDeadTime(form.value));
    2381            0 :         form.vals.push_back(o.str());
    2382            0 :         o.str("");
    2383            0 :         o.clear();
    2384            0 :         auto startNode = static_cast<int>(ReadEVBStartNode(form.value));
    2385            0 :         o << "EVB Start Node: 0x" << std::hex << startNode << " (" << std::dec << startNode << ")";
    2386            0 :         form.vals.push_back(o.str());
    2387            0 :         o.str("");
    2388            0 :         o.clear();
    2389            0 :         o << "EVB Number of Destination Nodes: " << std::dec << static_cast<int>(ReadEVBNumberOfDestinationNodes(form.value));
    2390            0 :         form.vals.push_back(o.str());
    2391            0 :         return form;
    2392            0 : }
    2393              : 
    2394              : /// Hardware Event Building Packet Control Info Register
    2395            0 : void DTCLib::DTC_Registers::SetEVBPacketControlInfo(uint16_t idlePacketWordCount,
    2396              :                                                                                                         uint8_t interpacketGap, uint8_t loopbackCalibratedOffset)
    2397              : {
    2398            0 :         uint32_t regVal = idlePacketWordCount << 16;
    2399            0 :         regVal |= interpacketGap << 8;
    2400            0 :         regVal |= loopbackCalibratedOffset;
    2401            0 :         WriteRegister_(regVal, DTC_Register_EVBPacketControl);
    2402            0 : }
    2403              : 
    2404              : /// Read the number of words in EVB idle packets
    2405            0 : uint16_t DTCLib::DTC_Registers::ReadEVBIdlePacketWordCount(std::optional<uint32_t> val)
    2406              : {
    2407            0 :         return static_cast<uint16_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
    2408              : }
    2409              : /// Read the EVB interpacket gap in units of GbE transmit clocks
    2410            0 : uint8_t DTCLib::DTC_Registers::ReadEVBInterpacketGap(std::optional<uint32_t> val)
    2411              : {
    2412            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 8);
    2413              : }
    2414              : /// Read the DTC's EVB delay offset in units of 200MHz CFO clocks, which should be calibrated by CFO-DTC loopback
    2415            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLoopbackCalibratedOffset(std::optional<uint32_t> val)
    2416              : {
    2417            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 0);
    2418              : }
    2419              : 
    2420              : /// Formats the Hardware Event Building Packet Control Info Register's current value for register dumps
    2421            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBPacketControlInfo()
    2422              : {
    2423            0 :         auto form = CreateFormatter(DTC_Register_EVBPacketControl);
    2424            0 :         form.description = "EVB Packet Control Info";
    2425            0 :         form.vals.push_back("");  // translation
    2426            0 :         std::stringstream o;
    2427            0 :         o << "Idle Packet Word Count:                           " << std::dec << static_cast<int>(ReadEVBIdlePacketWordCount(form.value));
    2428            0 :         form.vals.push_back(o.str());
    2429            0 :         o.str("");
    2430            0 :         o.clear();
    2431            0 :         o << "Interpacket Gap [GbE tx clocks]:                  " << std::dec << static_cast<int>(ReadEVBInterpacketGap(form.value));
    2432            0 :         form.vals.push_back(o.str());
    2433            0 :         o.str("");
    2434            0 :         o.clear();
    2435            0 :         o << "DTC's Loopback Calibrated Offset [200MHz clocks]: " << std::dec << static_cast<int>(ReadEVBLoopbackCalibratedOffset(form.value));
    2436            0 :         form.vals.push_back(o.str());
    2437            0 :         return form;
    2438            0 : }
    2439              : 
    2440              : /// Read theHardware Event Building Stats data based on type and DTC mac address
    2441            0 : uint32_t DTCLib::DTC_Registers::ReadEVBStats(DTC_EVBStatsType type, uint8_t dtc_mac, std::optional<uint32_t> val)
    2442              : {
    2443            0 :         if (val.has_value())                              // assum address is already setup when value is passed, and just read updated stat value
    2444            0 :                 return ReadRegister_(DTC_Register_EVBStats);  //*val;
    2445              : 
    2446            0 :         uint32_t t = static_cast<uint8_t>(type) << DTC_EVBStatsType_BRAM_TYPE_SIZE;
    2447            0 :         if (dtc_mac >= (1 << DTC_EVBStatsType_BRAM_TYPE_SIZE))
    2448              :         {
    2449            0 :                 __SS__ << "Illegal DTC MAC adress value: " << (int)dtc_mac << " must be < 2^" << DTC_EVBStatsType_BRAM_TYPE_SIZE << __E__;
    2450            0 :                 ss << otsStyleStackTrace() << __E__;
    2451            0 :                 __SS_THROW__;
    2452            0 :         }
    2453            0 :         t |= dtc_mac;  // address fully built now
    2454            0 :         __COUTT__ << "Read EVB Stat address: 0x" << std::hex << t << __E__;
    2455              : 
    2456            0 :         WriteRegister_(t, DTC_Register_EVBStats);
    2457              : 
    2458            0 :         return ReadRegister_(DTC_Register_EVBStats);
    2459              : }  // end ReadEVBStats()
    2460              : 
    2461              : // Get the last packet count and its timestamp for a DTC
    2462            0 : std::pair<uint32_t, std::chrono::steady_clock::time_point> DTCLib::DTC_Registers::getPacketCountInfo(uint8_t dtc) const
    2463              : {
    2464            0 :         auto i = lastPacketCount.find(dtc);
    2465            0 :         if (i != lastPacketCount.end())
    2466            0 :                 return i->second;
    2467            0 :         return {0, std::chrono::steady_clock::time_point::min()};
    2468              : }
    2469              : 
    2470              : // Update the packet count and timestamp and calculate packet rate for a DTC
    2471            0 : void DTCLib::DTC_Registers::updatePacketCount(uint8_t dtc, uint32_t currentCount)
    2472              : {
    2473            0 :         auto now = std::chrono::steady_clock::now();
    2474              : 
    2475            0 :         auto [lastCount, lastTime] = getPacketCountInfo(dtc);
    2476            0 :         if (lastTime == std::chrono::steady_clock::time_point::min())
    2477              :         {
    2478            0 :                 lastPacketCount[dtc] = {currentCount, now};
    2479            0 :                 return;
    2480              :         }
    2481              : 
    2482            0 :         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
    2483            0 :         if (ns > 1e6)
    2484              :         {
    2485            0 :                 double rate = (currentCount - lastCount) / (ns / 1e9);
    2486            0 :                 lastPacketRate[dtc] = rate;
    2487            0 :                 lastPacketCount[dtc] = {currentCount, now};
    2488              :         }
    2489              : }
    2490              : 
    2491              : // Get the most recent packet rate for a DTC
    2492            0 : double DTCLib::DTC_Registers::getLastPacketRate(uint8_t dtc) const
    2493              : {
    2494            0 :         auto i = lastPacketRate.find(dtc);
    2495            0 :         return i != lastPacketRate.end() ? i->second : 0.0;
    2496              : }
    2497              : 
    2498              : /// Formats the Hardware Event Building Stats data for all DTC mac addresses, as specified by the EVB Info 'Number Of Destination Nodes'
    2499            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBStats(DTCLib::DTC_EVBStatsType type /*  = DTC_EVBStatsType::DTC_EVBStatsType_All */)
    2500              : {
    2501            0 :         uint8_t t = static_cast<uint8_t>(type);
    2502            0 :         if (type == DTC_EVBStatsType::DTC_EVBStatsType_All)
    2503            0 :                 t = 0;
    2504            0 :         __COUTV__(t);
    2505              : 
    2506            0 :         auto form = CreateFormatter(DTC_Register_EVBStats, false /* getValue */);
    2507            0 :         form.description = "EVB Stats";
    2508            0 :         form.vals.push_back("");  // translation
    2509            0 :         std::stringstream o;
    2510              : 
    2511            0 :         uint8_t baseDTCAddress = ReadEVBStartNode();
    2512            0 :         uint8_t numOfDTCs = ReadEVBNumberOfDestinationNodes();
    2513              : 
    2514            0 :         __COUTV__(numOfDTCs);
    2515              : 
    2516            0 :         uint32_t idlePacketWordCount = (static_cast<uint32_t>(ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
    2517              : 
    2518            0 :         for (; t < DTC_EVBStatsType_BRAM_TYPE_COUNT; ++t)
    2519              :         {
    2520            0 :                 for (uint8_t d = 0; d < numOfDTCs; ++d)
    2521              :                 {
    2522            0 :                         uint32_t v = ReadEVBStats(DTC_EVBStatsType(t), d);
    2523              : 
    2524            0 :                         o << "BRAM Stat - ";
    2525            0 :                         switch (DTC_EVBStatsType(t))
    2526              :                         {
    2527            0 :                                 case DTC_EVBStatsType_RxCount:
    2528            0 :                                         if (v > 0 &&  // start time for rates as soon as there is non-zero data
    2529            0 :                                                 EVB_startDataTime ==
    2530            0 :                                                         std::chrono::steady_clock::time_point::min())
    2531            0 :                                                 EVB_startDataTime = std::chrono::steady_clock::now();
    2532              : 
    2533            0 :                                         EVB_endDataTime = std::chrono::steady_clock::now();
    2534              : 
    2535            0 :                                         o << "Received Packet Rate:                  ";
    2536            0 :                                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
    2537              : 
    2538              :                                         {
    2539            0 :                                                 auto now = std::chrono::steady_clock::now();
    2540            0 :                                                 auto [lastCount, lastTime] = getPacketCountInfo(d);
    2541              : 
    2542            0 :                                                 if (lastTime == std::chrono::steady_clock::time_point::min())
    2543              :                                                 {
    2544            0 :                                                         updatePacketCount(d, v);
    2545            0 :                                                         o << "Initializing";
    2546              :                                                 }
    2547              :                                                 else
    2548              :                                                 {
    2549            0 :                                                         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
    2550              : 
    2551            0 :                                                         if (ns > 1e6)  // prevent divide by 0
    2552              :                                                         {
    2553            0 :                                                                 double rate = (v - lastCount) / (ns / 1e9);
    2554            0 :                                                                 o << rate << " Packets/s";
    2555              : 
    2556            0 :                                                                 updatePacketCount(d, v);
    2557              :                                                         }
    2558              :                                                         else
    2559            0 :                                                                 o << "T too short.";
    2560              :                                                 }
    2561              :                                         }
    2562            0 :                                         form.vals.push_back(o.str());
    2563            0 :                                         o.str("");
    2564            0 :                                         o.clear();
    2565              : 
    2566            0 :                                         o << "Bram Stat - Received Packet Count:                 ";
    2567            0 :                                         break;
    2568            0 :                                 case DTC_EVBStatsType_RxLastSequenceTag:
    2569            0 :                                         o << "Last Received Sequence Tag:            ";
    2570            0 :                                         break;
    2571            0 :                                 case DTC_EVBStatsType_RxMissingPacketCount:
    2572            0 :                                         o << "Rx Missing Packet Count:               ";
    2573            0 :                                         break;
    2574            0 :                                 case DTC_EVBStatsType_RxByteCount:
    2575            0 :                                         o << "Received Byte Rate:                    ";
    2576            0 :                                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
    2577              : 
    2578            0 :                                         o << getLastPacketRate(d) * idlePacketWordCount * 8 << " Byte/s";
    2579            0 :                                         form.vals.push_back(o.str());
    2580            0 :                                         o.str("");
    2581            0 :                                         o.clear();
    2582              : 
    2583            0 :                                         o << "Bram Stat - Received Byte Count:                   ";
    2584            0 :                                         break;
    2585            0 :                                 case DTC_EVBStatsType_RxLastPacketArrival:
    2586            0 :                                         o << "Rx Last Packet Arrival [10gbe clocks]: ";
    2587            0 :                                         break;
    2588            0 :                                 case DTC_EVBStatsType_TxLastSequenceTag:
    2589            0 :                                         o << "Last Transmitted Sequence Tag:         ";
    2590            0 :                                         break;
    2591            0 :                                 case DTC_EVBStatsType_TravelTime:
    2592            0 :                                         o << "Travel Time [switch clocks]:           ";
    2593            0 :                                         break;
    2594            0 :                                 case DTC_EVBStatsType_TxIdleCount:
    2595            0 :                                         o << "TX Idle Packet Count:                  ";
    2596            0 :                                         break;
    2597            0 :                                 case DTC_EVBStatsType_RxIdleCount:
    2598            0 :                                         o << "RX Idle Packet Count:                  ";
    2599            0 :                                         break;
    2600            0 :                                 default:
    2601            0 :                                         __SS__ << "Invalid DTC EVB Stat type: " << t << __E__;
    2602            0 :                                         __SS_THROW__;
    2603              :                         }
    2604            0 :                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = " << std::hex << "0x" << std::setw(8) << v << "\t" << std::dec << v;
    2605            0 :                         form.vals.push_back(o.str());
    2606            0 :                         o.str("");
    2607            0 :                         o.clear();
    2608              :                 }  // end DTC mac address loop
    2609            0 :                 if (type != DTC_EVBStatsType::DTC_EVBStatsType_All) break;
    2610              :         }  // end type loop
    2611              : 
    2612            0 :         return form;
    2613            0 : }  // end FormatEVBStats()
    2614              : 
    2615              : /// <summary>
    2616              : /// Read the Reset bit of the SERDES IIC Bus
    2617              : /// </summary>
    2618              : /// <returns>Reset bit value</returns>
    2619            0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICInterfaceReset(std::optional<uint32_t> val)
    2620              : {
    2621            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESClock_IICBusControl));
    2622            0 :         return dataSet[31];
    2623              : }
    2624              : 
    2625              : /// <summary>
    2626              : /// Reset the SERDES IIC Bus
    2627              : /// </summary>
    2628            0 : void DTCLib::DTC_Registers::ResetSERDESOscillatorIICInterface()
    2629              : {
    2630            0 :         auto bs = std::bitset<32>();
    2631            0 :         bs[31] = 1;
    2632            0 :         WriteRegister_(bs.to_ulong(), DTC_Register_SERDESClock_IICBusControl);
    2633            0 :         while (ReadSERDESOscillatorIICInterfaceReset())
    2634              :         {
    2635            0 :                 usleep(1000);
    2636              :         }
    2637            0 : }
    2638              : 
    2639              : /// <summary>
    2640              : /// Read the current SERDES Oscillator clock speed
    2641              : /// </summary>
    2642              : /// <returns>Current SERDES clock speed</returns>
    2643            0 : DTCLib::DTC_SerdesClockSpeed DTCLib::DTC_Registers::ReadSERDESOscillatorClock(std::optional<uint32_t> val)
    2644              : {
    2645              :         // DTC register definition was removed, all DTC versions only were returning constant value
    2646            0 :         auto freq = 0x09502f90;  // 156.25mhz // ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, val);
    2647              : 
    2648              :         // Clocks should be accurate to 30 ppm
    2649            0 :         if (freq > 156250000 - 4687.5 && freq < 156250000 + 4687.5) return DTC_SerdesClockSpeed_3125Gbps;
    2650            0 :         if (freq > 125000000 - 3750 && freq < 125000000 + 3750) return DTC_SerdesClockSpeed_25Gbps;
    2651            0 :         return DTC_SerdesClockSpeed_Unknown;
    2652              : }
    2653              : /// <summary>
    2654              : /// Set the SERDES Oscillator clock speed for the given SERDES transfer rate
    2655              : /// </summary>
    2656              : /// <param name="speed">Clock speed to set</param>
    2657            0 : void DTCLib::DTC_Registers::SetSERDESOscillatorClock(DTC_SerdesClockSpeed speed)
    2658              : {
    2659              :         double targetFreq;
    2660            0 :         switch (speed)
    2661              :         {
    2662            0 :                 case DTC_SerdesClockSpeed_25Gbps:
    2663            0 :                         targetFreq = 125000000.0;
    2664            0 :                         break;
    2665            0 :                 case DTC_SerdesClockSpeed_3125Gbps:
    2666            0 :                         targetFreq = 156250000.0;
    2667            0 :                         break;
    2668            0 :                 default:
    2669            0 :                         targetFreq = 0.0;
    2670            0 :                         break;
    2671              :         }
    2672            0 :         if (SetNewOscillatorFrequency(DTC_OscillatorType_SERDES, targetFreq))
    2673              :         {
    2674            0 :                 for (auto& link : DTC_ROC_Links)
    2675              :                 {
    2676            0 :                         ResetSERDES(link, 1000);
    2677              :                 }
    2678            0 :                 ResetSERDES(DTC_Link_CFO, 1000);
    2679              :                 // ResetSERDES(DTC_Link_EVB, 1000);
    2680              :         }
    2681            0 : }
    2682              : 
    2683              : /// <summary>
    2684              : /// Set the Timing Oscillator clock to a given frequency
    2685              : /// </summary>
    2686              : /// <param name="freq">Frequency to set the Timing card Oscillator clock</param>
    2687            0 : void DTCLib::DTC_Registers::SetTimingOscillatorClock(uint32_t freq)
    2688              : {
    2689            0 :         double targetFreq = freq;
    2690            0 :         if (SetNewOscillatorFrequency(DTC_OscillatorType_Timing, targetFreq))
    2691              :         {
    2692            0 :                 ResetSERDES(DTC_Link_CFO, 1000);
    2693              :                 // ResetSERDES(DTC_Link_EVB, 1000);
    2694              :         }
    2695            0 : }
    2696              : 
    2697              : // /// <summary>
    2698              : // /// Formats the register's current value for register dumps
    2699              : // /// </summary>
    2700              : // /// <returns>RegisterFormatter object containing register information</returns>
    2701              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTimingSERDESOscillatorFrequency()
    2702              : // {
    2703              : //      auto form = CreateFormatter(DTC_Register_SERDESTimingCardOscillatorFrequency);
    2704              : //      form.description = "SERDES Timing Card Oscillator Reference Frequency";
    2705              : //      std::stringstream o;
    2706              : //      o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_CFO, form.value);
    2707              : //      form.vals.push_back(o.str());
    2708              : //      return form;
    2709              : // }
    2710              : 
    2711              : // /// <summary>
    2712              : // /// Formats the register's current value for register dumps
    2713              : // /// </summary>
    2714              : // /// <returns>RegisterFormatter object containing register information</returns>
    2715              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMainBoardSERDESOscillatorFrequency()
    2716              : // {
    2717              : //      auto form = CreateFormatter(DTC_Register_SERDESReferenceClockFrequency);
    2718              : //      form.description = "SERDES Main Board Oscillator Reference Frequency";
    2719              : //      std::stringstream o;
    2720              : //      o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, form.value);
    2721              : //      form.vals.push_back(o.str());
    2722              : //      return form;
    2723              : // }
    2724              : /// <summary>
    2725              : /// Formats the register's current value for register dumps
    2726              : /// </summary>
    2727              : /// <returns>RegisterFormatter object containing register information</returns>
    2728            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESOscillatorControl()
    2729              : {
    2730            0 :         auto form = CreateFormatter(DTC_Register_SERDESClock_IICBusControl);
    2731            0 :         form.description = "SERDES Oscillator IIC Bus Control";
    2732            0 :         form.vals.push_back(std::string("Reset:  [") + (ReadSERDESOscillatorIICInterfaceReset(form.value) ? "x" : " ") + "]");
    2733            0 :         return form;
    2734            0 : }
    2735              : 
    2736              : // FIFO Full Error Flags Registers
    2737              : /// <summary>
    2738              : /// Clear all FIFO Full Error Flags for the given link
    2739              : /// </summary>
    2740              : /// <param name="link">Link to clear</param>
    2741            0 : void DTCLib::DTC_Registers::ClearFIFOFullErrorFlags(DTC_Link_ID const& link)
    2742              : {
    2743            0 :         auto flags = ReadFIFOFullErrorFlags(link);
    2744            0 :         std::bitset<32> data0 = 0;
    2745            0 :         std::bitset<32> data1 = 0;
    2746            0 :         std::bitset<32> data2 = 0;
    2747              : 
    2748            0 :         data0[link] = flags.OutputData;
    2749            0 :         data0[link + 8] = flags.CFOLinkInput;
    2750            0 :         data0[link + 16] = flags.ReadoutRequestOutput;
    2751            0 :         data0[link + 24] = flags.DataRequestOutput;
    2752            0 :         data1[link] = flags.OtherOutput;
    2753            0 :         data1[link + 8] = flags.OutputDCS;
    2754            0 :         data1[link + 16] = flags.OutputDCSStage2;
    2755            0 :         data1[link + 24] = flags.DataInput;
    2756            0 :         data2[link] = flags.DCSStatusInput;
    2757              : 
    2758            0 :         WriteRegister_(data0.to_ulong(), DTC_Register_FIFOFullErrorFlag0);
    2759            0 :         WriteRegister_(data1.to_ulong(), DTC_Register_FIFOFullErrorFlag1);
    2760            0 :         WriteRegister_(data2.to_ulong(), DTC_Register_FIFOFullErrorFlag2);
    2761            0 : }
    2762              : 
    2763              : /// <summary>
    2764              : /// Read the FIFO Full Error/Status Flags for the given link
    2765              : /// </summary>
    2766              : /// <param name="link">Link to read</param>
    2767              : /// <returns>DTC_FIFOFullErrorFlags object</returns>
    2768            0 : DTCLib::DTC_FIFOFullErrorFlags DTCLib::DTC_Registers::ReadFIFOFullErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val0,
    2769              :                                                                                                                                                          std::optional<uint32_t> val1, std::optional<uint32_t> val2)
    2770              : {
    2771            0 :         std::bitset<32> data0 = val0.has_value() ? *val0 : ReadRegister_(DTC_Register_FIFOFullErrorFlag0);
    2772            0 :         std::bitset<32> data1 = val1.has_value() ? *val1 : ReadRegister_(DTC_Register_FIFOFullErrorFlag1);
    2773            0 :         std::bitset<32> data2 = val2.has_value() ? *val2 : ReadRegister_(DTC_Register_FIFOFullErrorFlag2);
    2774            0 :         DTC_FIFOFullErrorFlags flags;
    2775              : 
    2776            0 :         flags.OutputData = data0[link];
    2777            0 :         flags.CFOLinkInput = data0[link + 8];
    2778            0 :         flags.ReadoutRequestOutput = data0[link + 16];
    2779            0 :         flags.DataRequestOutput = data0[link + 24];
    2780            0 :         flags.OtherOutput = data1[link];
    2781            0 :         flags.OutputDCS = data1[link + 8];
    2782            0 :         flags.OutputDCSStage2 = data1[link + 16];
    2783            0 :         flags.DataInput = data1[link + 24];
    2784            0 :         flags.DCSStatusInput = data2[link];
    2785              : 
    2786            0 :         return flags;
    2787              : }
    2788              : 
    2789              : /// <summary>
    2790              : /// Formats the register's current value for register dumps
    2791              : /// </summary>
    2792              : /// <returns>RegisterFormatter object containing register information</returns>
    2793            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag0()
    2794              : {
    2795            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag0);
    2796            0 :         form.description = "FIFO Full Error Flags 0";
    2797            0 :         form.vals.push_back("       ([DataRequest, ReadoutRequest, CFOLink, OutputData])");
    2798            0 :         for (auto r : DTC_ROC_Links)
    2799              :         {
    2800            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2801            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataRequestOutput ? "x" : " ") + "," +
    2802            0 :                                                         (re.ReadoutRequestOutput ? "x" : " ") + "," + (re.CFOLinkInput ? "x" : " ") + "," +
    2803            0 :                                                         (re.OutputData ? "x" : " ") + "]");
    2804              :         }
    2805            0 :         return form;
    2806            0 : }
    2807              : 
    2808              : /// <summary>
    2809              : /// Formats the register's current value for register dumps
    2810              : /// </summary>
    2811              : /// <returns>RegisterFormatter object containing register information</returns>
    2812            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag1()
    2813              : {
    2814            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag1);
    2815            0 :         form.description = "FIFO Full Error Flags 1";
    2816            0 :         form.vals.push_back("       ([DataInput, OutputDCSStage2, OutputDCS, OtherOutput])");
    2817            0 :         for (auto r : DTC_ROC_Links)
    2818              :         {
    2819            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2820            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataInput ? "x" : " ") + "," +
    2821            0 :                                                         (re.OutputDCSStage2 ? "x" : " ") + "," + (re.OutputDCS ? "x" : " ") + "," +
    2822            0 :                                                         (re.OtherOutput ? "x" : " ") + "]");
    2823              :         }
    2824              :         {
    2825            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
    2826            0 :                 form.vals.push_back(std::string("CFO:    [") + +(ce.DataInput ? "x" : " ") + "," +
    2827            0 :                                                         (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
    2828            0 :                                                         (ce.OtherOutput ? "x" : " ") + "]");
    2829              :         }
    2830              :         {
    2831            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
    2832            0 :                 form.vals.push_back(std::string("EVB:    [") + +(ce.DataInput ? "x" : " ") + "," +
    2833            0 :                                                         (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
    2834            0 :                                                         (ce.OtherOutput ? "x" : " ") + "]");
    2835              :         }
    2836            0 :         return form;
    2837            0 : }
    2838              : 
    2839              : /// <summary>
    2840              : /// Formats the register's current value for register dumps
    2841              : /// </summary>
    2842              : /// <returns>RegisterFormatter object containing register information</returns>
    2843            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag2()
    2844              : {
    2845            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag2);
    2846            0 :         form.description = "FIFO Full Error Flags 2";
    2847            0 :         form.vals.push_back("       ([DCSStatusInput])");
    2848            0 :         for (auto r : DTC_ROC_Links)
    2849              :         {
    2850            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2851            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DCSStatusInput ? "x" : " ") + "]");
    2852              :         }
    2853              :         {
    2854            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
    2855            0 :                 form.vals.push_back(std::string("CFO:    [") + (ce.DCSStatusInput ? "x" : " ") + "]");
    2856              :         }
    2857              :         {
    2858            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
    2859            0 :                 form.vals.push_back(std::string("EVB:    [") + (ce.DCSStatusInput ? "x" : " ") + "]");
    2860              :         }
    2861            0 :         return form;
    2862            0 : }
    2863              : 
    2864              : // Receive Packet Error Register
    2865              : /// <summary>
    2866              : /// Clear the Packet Error Flag for the given link
    2867              : /// </summary>
    2868              : /// <param name="link">Link to clear</param>
    2869            0 : void DTCLib::DTC_Registers::ClearPacketError(DTC_Link_ID const& link)
    2870              : {
    2871            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
    2872            0 :         data[static_cast<int>(link) + 8] = 0;
    2873            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
    2874            0 : }
    2875              : 
    2876              : /// <summary>
    2877              : /// Read the Packet Error Flag for the given link
    2878              : /// </summary>
    2879              : /// <param name="link">Link to read</param>
    2880              : /// <returns>True if the Packet Error Flag is set</returns>
    2881            0 : bool DTCLib::DTC_Registers::ReadPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2882              : {
    2883            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
    2884            0 :         return data[static_cast<int>(link) + 8];
    2885              : }
    2886              : 
    2887              : /// <summary>
    2888              : /// Clear the Packet CRC Error Flag for the given link
    2889              : /// </summary>
    2890              : /// <param name="link">Link to clear</param>
    2891            0 : void DTCLib::DTC_Registers::ClearPacketCRCError(DTC_Link_ID const& link)
    2892              : {
    2893            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
    2894            0 :         data[static_cast<int>(link)] = 0;
    2895            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
    2896            0 : }
    2897              : 
    2898              : /// <summary>
    2899              : /// Read the Packet CRC Error Flag for the given link
    2900              : /// </summary>
    2901              : /// <param name="link">Link to read</param>
    2902              : /// <returns>True if the Packet CRC Error Flag is set</returns>
    2903            0 : bool DTCLib::DTC_Registers::ReadPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2904              : {
    2905            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
    2906            0 :         return data[static_cast<int>(link)];
    2907              : }
    2908              : 
    2909              : /// <summary>
    2910              : /// Formats the register's current value for register dumps
    2911              : /// </summary>
    2912              : /// <returns>RegisterFormatter object containing register information</returns>
    2913            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatReceivePacketError()
    2914              : {
    2915            0 :         auto form = CreateFormatter(DTC_Register_ReceivePacketError);
    2916            0 :         form.description = "Receive Packet Error";
    2917            0 :         form.vals.push_back("       ([CRC, PacketError])");
    2918            0 :         for (auto r : DTC_ROC_Links)
    2919            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2920            0 :                                                         (ReadPacketCRCError(r, form.value) ? "x" : " ") + "," +
    2921            0 :                                                         (ReadPacketError(r, form.value) ? "x" : " ") + "]");
    2922            0 :         form.vals.push_back(std::string("CFO:    [") +
    2923            0 :                                                 (ReadPacketCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    2924            0 :                                                 (ReadPacketError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    2925            0 :         form.vals.push_back(std::string("EVB:    [") +
    2926            0 :                                                 (ReadPacketCRCError(DTC_Link_EVB, form.value) ? "x" : " ") + "," +
    2927            0 :                                                 (ReadPacketError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    2928            0 :         return form;
    2929            0 : }
    2930              : 
    2931              : // CFO Emulation Timestamp Registers
    2932              : /// <summary>
    2933              : /// Set the starting DTC_EventWindowTag for the CFO Emulator
    2934              : /// </summary>
    2935              : /// <param name="ts">Starting Timestamp for CFO Emulation</param>
    2936            0 : void DTCLib::DTC_Registers::SetCFOEmulationTimestamp(const DTC_EventWindowTag& ts)
    2937              : {
    2938            0 :         auto timestamp = ts.GetEventWindowTag();
    2939            0 :         auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
    2940            0 :         timestamp >>= 32;
    2941            0 :         auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
    2942              : 
    2943            0 :         WriteRegister_(timestampLow, DTC_Register_CFOEmulation_TimestampLow);
    2944            0 :         WriteRegister_(timestampHigh, DTC_Register_CFOEmulation_TimestampHigh);
    2945            0 : }
    2946              : 
    2947              : /// <summary>
    2948              : /// Read the starting DTC_EventWindowTag for the CFO Emulator
    2949              : /// </summary>
    2950              : /// <returns>DTC_EventWindowTag object</returns>
    2951            0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadCFOEmulationTimestamp(std::optional<uint32_t> val)
    2952              : {
    2953            0 :         auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
    2954            0 :         DTC_EventWindowTag output;
    2955            0 :         output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh)));
    2956            0 :         return output;
    2957            0 : }
    2958              : 
    2959              : /// <summary>
    2960              : /// Formats the register's current value for register dumps
    2961              : /// </summary>
    2962              : /// <returns>RegisterFormatter object containing register information</returns>
    2963            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampLow()
    2964              : {
    2965            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampLow);
    2966            0 :         form.description = "CFO Emulation Timestamp Low";
    2967            0 :         std::stringstream o;
    2968            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
    2969            0 :         form.vals.push_back(o.str());
    2970            0 :         return form;
    2971            0 : }
    2972              : 
    2973              : /// <summary>
    2974              : /// Formats the register's current value for register dumps
    2975              : /// </summary>
    2976              : /// <returns>RegisterFormatter object containing register information</returns>
    2977            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampHigh()
    2978              : {
    2979            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampHigh);
    2980            0 :         form.description = "CFO Emulation Timestamp High";
    2981            0 :         std::stringstream o;
    2982            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh);
    2983            0 :         form.vals.push_back(o.str());
    2984            0 :         return form;
    2985            0 : }
    2986              : 
    2987              : // CFO Emulation Delay Measure
    2988              : /// <summary>
    2989              : /// Read the Delay Measure acquired with the CFO Emulator Loopback Test
    2990              : /// </summary>
    2991            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationLoopbackDelayMeasure(std::optional<uint32_t> val)
    2992              : {
    2993            0 :         uint32_t readVal = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    2994            0 :         uint32_t i = 0;
    2995            0 :         while (!(readVal >> 31))
    2996              :         {
    2997            0 :                 if (i > 1000)
    2998              :                 {
    2999            0 :                         __SS__ << "Timeout looking for the CFO Emulator Loopback Test to complete... readval: 0x" << std::hex << readVal << __E__;
    3000            0 :                         __SS_THROW__;
    3001            0 :                 }
    3002              : 
    3003            0 :                 usleep(10000);
    3004            0 :                 readVal = ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    3005            0 :                 ++i;
    3006              :         }
    3007            0 :         return readVal & (~(1 << 31));  // clear the Ready bit from return value
    3008              : }
    3009              : 
    3010              : /// <summary>
    3011              : /// Formats the register's current value for register dumps
    3012              : /// </summary>
    3013              : /// <returns>RegisterFormatter object containing register information</returns>
    3014            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationLoopbackDelayMeasure()
    3015              : {
    3016            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    3017            0 :         form.description = "CFO Emu. Loopback Delay Measure";
    3018            0 :         std::stringstream o;
    3019            0 :         o << "0x" << std::hex << ReadCFOEmulationLoopbackDelayMeasure(form.value) << std::dec << "(" << double(1.0) * ReadCFOEmulationLoopbackDelayMeasure(form.value) * 5 /*ns for 200MHz period*/ / 8.0 /* for 8 samples */ << " ns)";
    3020            0 :         form.vals.push_back(o.str());
    3021            0 :         return form;
    3022            0 : }
    3023              : 
    3024              : // CFO Emulation Request Interval Register
    3025              : /// <summary>
    3026              : /// Set the clock interval between CFO Emulator Event Windows.
    3027              : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
    3028              : /// </summary>
    3029              : /// <param name="interval">Clock cycles between Event Window Markers</param>
    3030            0 : void DTCLib::DTC_Registers::SetCFOEmulationEventWindowInterval(uint32_t interval)
    3031              : {
    3032            0 :         WriteRegister_(interval, DTC_Register_CFOEmulation_HeartbeatInterval);
    3033            0 : }
    3034              : 
    3035              : /// <summary>
    3036              : /// Read the clock interval between CFO Emulator Event Windows.
    3037              : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
    3038              : /// </summary>
    3039              : /// <returns>Clock cycles between Event Window Markers</returns>
    3040            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationEventWindowInterval(std::optional<uint32_t> val)
    3041              : {
    3042            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_HeartbeatInterval);
    3043              : }
    3044              : 
    3045              : /// <summary>
    3046              : /// Formats the register's current value for register dumps
    3047              : /// </summary>
    3048              : /// <returns>RegisterFormatter object containing register information</returns>
    3049            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationEventWindowInterval()
    3050              : {
    3051            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_HeartbeatInterval);
    3052            0 :         form.description = "CFO Emu. EWM Interval";
    3053            0 :         std::stringstream o;
    3054            0 :         o << "0x" << std::hex << ReadCFOEmulationEventWindowInterval(form.value);
    3055            0 :         form.vals.push_back(o.str());
    3056            0 :         return form;
    3057            0 : }
    3058              : 
    3059              : // CFO Emulation Number of Requests Register
    3060              : /// <summary>
    3061              : /// Set the number of Readout Requests the CFO Emulator is configured to send.
    3062              : /// A value of 0 means that the CFO Emulator will send requests continuously.
    3063              : /// </summary>
    3064              : /// <param name="NumHeartbeats">Number of Readout Requests the CFO Emulator will send</param>
    3065            0 : void DTCLib::DTC_Registers::SetCFOEmulationNumHeartbeats(uint32_t NumHeartbeats)
    3066              : {
    3067            0 :         WriteRegister_(NumHeartbeats, DTC_Register_CFOEmulation_NumHeartbeats);
    3068            0 : }
    3069              : 
    3070              : /// <summary>
    3071              : /// Reads the number of Readout Requests the CFO Emulator is configured to send.
    3072              : /// A value of 0 means that the CFO Emulator will send requests continuously.
    3073              : /// </summary>
    3074              : /// <returns>Number of Readout Requests the CFO Emulator will send</returns>
    3075            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumHeartbeats(std::optional<uint32_t> val)
    3076              : {
    3077            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumHeartbeats);
    3078              : }
    3079              : 
    3080              : /// <summary>
    3081              : /// Formats the register's current value for register dumps
    3082              : /// </summary>
    3083              : /// <returns>RegisterFormatter object containing register information</returns>
    3084            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumHeartbeats()
    3085              : {
    3086            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_NumHeartbeats);
    3087            0 :         form.description = "CFO Emulator Number Requests";
    3088            0 :         std::stringstream o;
    3089            0 :         o << "0x" << std::hex << ReadCFOEmulationNumHeartbeats(form.value);
    3090            0 :         form.vals.push_back(o.str());
    3091            0 :         return form;
    3092            0 : }
    3093              : 
    3094              : // CFO Emulation Number of Packets Registers
    3095              : /// <summary>
    3096              : /// Set the number of packets the CFO Emulator will request from the link
    3097              : /// </summary>
    3098              : /// <param name="link">Link to set</param>
    3099              : /// <param name="numPackets">Number of packets to request</param>
    3100            0 : void DTCLib::DTC_Registers::SetROCEmulationNumPackets(DTC_Link_ID const& link_in, uint16_t numPackets)
    3101              : {
    3102            0 :         uint16_t data = numPackets & 0x7FF;
    3103              :         DTC_Register reg;
    3104              : 
    3105            0 :         for (const auto& link : DTC_ROC_Links)
    3106              :         {
    3107            0 :                 if (!(link_in == DTC_Link_ALL || link_in == link))
    3108            0 :                         continue;  // skip ROC links that should not be set
    3109              : 
    3110            0 :                 switch (link)
    3111              :                 {
    3112            0 :                         case DTC_Link_0:
    3113              :                         case DTC_Link_1:
    3114            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
    3115            0 :                                 break;
    3116            0 :                         case DTC_Link_2:
    3117              :                         case DTC_Link_3:
    3118            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
    3119            0 :                                 break;
    3120            0 :                         case DTC_Link_4:
    3121              :                         case DTC_Link_5:
    3122            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
    3123            0 :                                 break;
    3124            0 :                         default: {
    3125            0 :                                 __SS__ << "Illegal link " << link << " specified." << __E__;
    3126            0 :                                 __SS_THROW__;
    3127            0 :                         }
    3128              :                 }
    3129              : 
    3130            0 :                 auto regval = ReadRegister_(reg);
    3131            0 :                 auto upper = (regval & 0xFFFF0000) >> 16;
    3132            0 :                 auto lower = regval & 0x0000FFFF;
    3133            0 :                 if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
    3134              :                 {
    3135            0 :                         lower = data;
    3136              :                 }
    3137              :                 else
    3138              :                 {
    3139            0 :                         upper = data;
    3140              :                 }
    3141            0 :                 WriteRegister_((upper << 16) + lower, reg);
    3142              :         }  // end link write loop
    3143            0 : }
    3144              : 
    3145              : /// <summary>
    3146              : /// Read the requested number of packets the ROC Emulator will generate from the given link
    3147              : /// </summary>
    3148              : /// <param name="link">Link to read</param>
    3149              : /// <returns>Number of packets generated by the ROC Emulator</returns>
    3150            0 : uint16_t DTCLib::DTC_Registers::ReadROCEmulationNumPackets(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3151              : {
    3152              :         DTC_Register reg;
    3153            0 :         switch (link)
    3154              :         {
    3155            0 :                 case DTC_Link_0:
    3156              :                 case DTC_Link_1:
    3157            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
    3158            0 :                         break;
    3159            0 :                 case DTC_Link_2:
    3160              :                 case DTC_Link_3:
    3161            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
    3162            0 :                         break;
    3163            0 :                 case DTC_Link_4:
    3164              :                 case DTC_Link_5:
    3165            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
    3166            0 :                         break;
    3167            0 :                 default: {
    3168            0 :                         __SS__ << "Illegal link " << link << " specified." << __E__;
    3169            0 :                         __SS_THROW__;
    3170            0 :                 }
    3171              :         }
    3172              : 
    3173            0 :         auto regval = val.has_value() ? *val : ReadRegister_(reg);
    3174            0 :         auto upper = (regval & 0xFFFF0000) >> 16;
    3175            0 :         auto lower = regval & 0x0000FFFF;
    3176            0 :         if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
    3177              :         {
    3178            0 :                 return static_cast<uint16_t>(lower);
    3179              :         }
    3180            0 :         return static_cast<uint16_t>(upper);
    3181              : }
    3182              : 
    3183              : /// <summary>
    3184              : /// Formats the register's current value for register dumps
    3185              : /// </summary>
    3186              : /// <returns>RegisterFormatter object containing register information</returns>
    3187            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink01()
    3188              : {
    3189            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks10);
    3190            0 :         form.description = "ROC Emulator Num Packets R0,1";
    3191            0 :         form.vals.push_back("");  // translation
    3192            0 :         std::stringstream o;
    3193            0 :         o << "Link 0: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_0, form.value);
    3194            0 :         form.vals.push_back(o.str());
    3195            0 :         o.str("");
    3196            0 :         o.clear();
    3197            0 :         o << "Link 1: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_1, form.value);
    3198            0 :         form.vals.push_back(o.str());
    3199            0 :         return form;
    3200            0 : }
    3201              : 
    3202              : /// <summary>
    3203              : /// Formats the register's current value for register dumps
    3204              : /// </summary>
    3205              : /// <returns>RegisterFormatter object containing register information</returns>
    3206            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink23()
    3207              : {
    3208            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks32);
    3209            0 :         form.description = "ROC Emulator Num Packets R2,3";
    3210            0 :         form.vals.push_back("");  // translation
    3211            0 :         std::stringstream o;
    3212            0 :         o << "Link 2: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_2, form.value);
    3213            0 :         form.vals.push_back(o.str());
    3214            0 :         o.str("");
    3215            0 :         o.clear();
    3216            0 :         o << "Link 3: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_3, form.value);
    3217            0 :         form.vals.push_back(o.str());
    3218            0 :         return form;
    3219            0 : }
    3220              : 
    3221              : /// <summary>
    3222              : /// Formats the register's current value for register dumps
    3223              : /// </summary>
    3224              : /// <returns>RegisterFormatter object containing register information</returns>
    3225            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink45()
    3226              : {
    3227            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks54);
    3228            0 :         form.description = "ROC Emulator Num Packets R4,5";
    3229            0 :         form.vals.push_back("");  // translation
    3230            0 :         std::stringstream o;
    3231            0 :         o << "Link 4: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_4, form.value);
    3232            0 :         form.vals.push_back(o.str());
    3233            0 :         o.str("");
    3234            0 :         o.clear();
    3235            0 :         o << "Link 5: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_5, form.value);
    3236            0 :         form.vals.push_back(o.str());
    3237            0 :         return form;
    3238            0 : }
    3239              : 
    3240              : // CFO Emulation Number of Null Heartbeats Register
    3241              : /// <summary>
    3242              : /// Set the number of null heartbeats the CFO Emulator will generate following the requested ones
    3243              : /// </summary>
    3244              : /// <param name="count">Number of null heartbeats to generate</param>
    3245            0 : void DTCLib::DTC_Registers::SetCFOEmulationNumNullHeartbeats(const uint32_t& count)
    3246              : {
    3247            0 :         WriteRegister_(count, DTC_Register_CFOEmulation_NumNullHeartbeats);
    3248            0 : }
    3249              : 
    3250              : /// <summary>
    3251              : /// Read the requested number of null heartbeats that will follow the configured heartbeats from the CFO Emulator
    3252              : /// </summary>
    3253              : /// <returns>Number of null heartbeats to follow "live" heartbeats</returns>
    3254            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumNullHeartbeats(std::optional<uint32_t> val)
    3255              : {
    3256            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumNullHeartbeats);
    3257              : }
    3258              : 
    3259              : /// <summary>
    3260              : /// Formats the register's current value for register dumps
    3261              : /// </summary>
    3262              : /// <returns>RegisterFormatter object containing register information</returns>
    3263            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumNullHeartbeats()
    3264              : {
    3265            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_NumNullHeartbeats);
    3266            0 :         form.description = "CFO Emulator Num Null Heartbeats";
    3267            0 :         form.vals.push_back(std::to_string(ReadCFOEmulationNumNullHeartbeats(form.value)));
    3268            0 :         return form;
    3269            0 : }
    3270              : 
    3271            0 : void DTCLib::DTC_Registers::SetCFOEventModeRequiredMask(const uint32_t& mask)
    3272              : {
    3273            0 :         WriteRegister_(mask, DTC_Register_CFOEventModeRequiredMask);
    3274            0 : }
    3275            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEventModeRequiredMask(std::optional<uint32_t> val)
    3276              : {
    3277            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEventModeRequiredMask);
    3278              : }
    3279            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEventModeRequiredMask()
    3280              : {
    3281            0 :         auto form = CreateFormatter(DTC_Register_CFOEventModeRequiredMask);
    3282            0 :         form.description = "CFO Emulation Event Mode Required Mask";
    3283            0 :         std::stringstream o;
    3284            0 :         o << "0x" << std::hex << ReadCFOEventModeRequiredMask(form.value);
    3285            0 :         form.vals.push_back(o.str());
    3286            0 :         return form;
    3287            0 : }
    3288              : 
    3289              : // CFO Emulation Event Mode Bytes Registers
    3290              : /// <summary>
    3291              : /// Set the CFO Emulation Event Mode 48 bits
    3292              : /// </summary>
    3293            0 : void DTCLib::DTC_Registers::SetCFOEmulationEventMode(const uint64_t& eventMode)
    3294              : {
    3295            0 :         WriteRegister_(eventMode, DTC_Register_CFOEmulation_EventMode1);
    3296            0 :         WriteRegister_(eventMode >> 32, DTC_Register_CFOEmulation_EventMode2);
    3297            0 : }
    3298            0 : uint64_t DTCLib::DTC_Registers::ReadCFOEmulationEventMode()
    3299              : {
    3300            0 :         uint64_t eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode2);
    3301            0 :         eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode1) |
    3302            0 :                                 (eventMode << 32);
    3303            0 :         return eventMode;
    3304              : }
    3305              : 
    3306              : /// <summary>
    3307              : /// Set the given CFO Emulation Mode byte to the given value
    3308              : /// </summary>
    3309              : /// <param name="byteNum">Byte to set. Valid range is 0-5</param>
    3310              : /// <param name="data">Data for byte</param>
    3311            0 : void DTCLib::DTC_Registers::SetCFOEmulationModeByte(const uint8_t& byteNum, uint8_t data)
    3312              : {
    3313              :         DTC_Register reg;
    3314            0 :         if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
    3315              :         {
    3316            0 :                 reg = DTC_Register_CFOEmulation_EventMode1;
    3317              :         }
    3318            0 :         else if (byteNum == 4 || byteNum == 5)
    3319              :         {
    3320            0 :                 reg = DTC_Register_CFOEmulation_EventMode2;
    3321              :         }
    3322              :         else
    3323              :         {
    3324            0 :                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3325            0 :                 __SS_THROW__;
    3326            0 :         }
    3327            0 :         auto regVal = ReadRegister_(reg);
    3328              : 
    3329            0 :         switch (byteNum)
    3330              :         {
    3331            0 :                 case 0:
    3332            0 :                         regVal = (regVal & 0xFFFFFF00) + data;
    3333            0 :                         break;
    3334            0 :                 case 1:
    3335            0 :                         regVal = (regVal & 0xFFFF00FF) + (data << 8);
    3336            0 :                         break;
    3337            0 :                 case 2:
    3338            0 :                         regVal = (regVal & 0xFF00FFFF) + (data << 16);
    3339            0 :                         break;
    3340            0 :                 case 3:
    3341            0 :                         regVal = (regVal & 0x00FFFFFF) + (data << 24);
    3342            0 :                         break;
    3343            0 :                 case 4:
    3344            0 :                         regVal = (regVal & 0xFF00) + data;
    3345            0 :                         break;
    3346            0 :                 case 5:
    3347            0 :                         regVal = (regVal & 0x00FF) + (data << 8);
    3348            0 :                         break;
    3349            0 :                 default:
    3350              :                         // impossible
    3351              :                         {
    3352            0 :                                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3353            0 :                                 __SS_THROW__;
    3354            0 :                         }
    3355              :         }
    3356              : 
    3357            0 :         WriteRegister_(regVal, reg);
    3358            0 : }
    3359              : 
    3360              : /// <summary>
    3361              : /// Read the given CFO Emulation Mode byte
    3362              : /// </summary>
    3363              : /// <param name="byteNum">Byte to read. Valid range is 0-5</param>
    3364              : /// <returns>Current value of the mode byte</returns>
    3365            0 : uint8_t DTCLib::DTC_Registers::ReadCFOEmulationModeByte(const uint8_t& byteNum, std::optional<uint32_t> val)
    3366              : {
    3367              :         DTC_Register reg;
    3368            0 :         if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
    3369              :         {
    3370            0 :                 reg = DTC_Register_CFOEmulation_EventMode1;
    3371              :         }
    3372            0 :         else if (byteNum == 4 || byteNum == 5)
    3373              :         {
    3374            0 :                 reg = DTC_Register_CFOEmulation_EventMode2;
    3375              :         }
    3376              :         else
    3377              :         {
    3378            0 :                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3379            0 :                 __SS_THROW__;
    3380            0 :         }
    3381            0 :         auto regVal = val.has_value() ? *val : ReadRegister_(reg);
    3382              : 
    3383            0 :         switch (byteNum)
    3384              :         {
    3385            0 :                 case 0:
    3386            0 :                         return static_cast<uint8_t>(regVal & 0xFF);
    3387            0 :                 case 1:
    3388            0 :                         return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
    3389            0 :                 case 2:
    3390            0 :                         return static_cast<uint8_t>((regVal & 0xFF0000) >> 16);
    3391            0 :                 case 3:
    3392            0 :                         return static_cast<uint8_t>((regVal & 0xFF000000) >> 24);
    3393            0 :                 case 4:
    3394            0 :                         return static_cast<uint8_t>(regVal & 0xFF);
    3395            0 :                 case 5:
    3396            0 :                         return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
    3397            0 :                 default:
    3398              :                         // impossible
    3399              :                         {
    3400            0 :                                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3401            0 :                                 __SS_THROW__;
    3402            0 :                         }
    3403              :         }
    3404              : }
    3405              : 
    3406              : /// <summary>
    3407              : /// Formats the register's current value for register dumps
    3408              : /// </summary>
    3409              : /// <returns>RegisterFormatter object containing register information</returns>
    3410            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes03()
    3411              : {
    3412            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode1);
    3413            0 :         form.description = "CFO Emulation Event Mode Bytes 0-3";
    3414            0 :         form.vals.push_back("");  // translation
    3415            0 :         std::ostringstream o;
    3416            0 :         o << "Byte 0: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(0, form.value));
    3417            0 :         form.vals.push_back(o.str());
    3418            0 :         o.str("");
    3419            0 :         o.clear();
    3420            0 :         o << "Byte 1: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(1, form.value));
    3421            0 :         form.vals.push_back(o.str());
    3422            0 :         o.str("");
    3423            0 :         o.clear();
    3424            0 :         o << "Byte 2: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(2, form.value));
    3425            0 :         form.vals.push_back(o.str());
    3426            0 :         o.str("");
    3427            0 :         o.clear();
    3428            0 :         o << "Byte 3: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(3, form.value));
    3429            0 :         form.vals.push_back(o.str());
    3430            0 :         return form;
    3431            0 : }
    3432              : 
    3433              : /// <summary>
    3434              : /// Formats the register's current value for register dumps
    3435              : /// </summary>
    3436              : /// <returns>RegisterFormatter object containing register information</returns>
    3437            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes45()
    3438              : {
    3439            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode2);
    3440            0 :         form.description = "CFO Emulation Event Mode Bytes 4-5";
    3441            0 :         form.vals.push_back("");  // translation
    3442            0 :         std::ostringstream o;
    3443            0 :         o << "Byte 4: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(4, form.value));
    3444            0 :         form.vals.push_back(o.str());
    3445            0 :         o.str("");
    3446            0 :         o.clear();
    3447            0 :         o << "Byte 5: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(5, form.value));
    3448            0 :         form.vals.push_back(o.str());
    3449            0 :         o.str("");
    3450            0 :         o.clear();
    3451            0 :         return form;
    3452            0 : }
    3453              : 
    3454              : /// <summary>
    3455              : /// Set the DebugType used by the CFO Emulator
    3456              : /// </summary>
    3457              : /// <param name="type">The DTC_DebugType the CFO Emulator will fill into Readout Requests</param>
    3458              : // void DTCLib::DTC_Registers::SetCFOEmulationDebugType(DTC_DebugType type)
    3459              : //{
    3460              : //      std::bitset<32> data = type & 0xF;
    3461              : //      data[16] = ReadDebugPacketMode();
    3462              : //      WriteRegister_(data.to_ulong(), DTC_Register_DebugPacketType);
    3463              : // }
    3464              : 
    3465              : /// <summary>
    3466              : /// Read the DebugType field filled into Readout Requests generated by the CFO Emulator
    3467              : /// </summary>
    3468              : /// <returns>The DTC_DebugType used by the CFO Emulator</returns>
    3469              : // DTCLib::DTC_DebugType DTCLib::DTC_Registers::ReadCFOEmulationDebugType(std::optional<uint32_t> val)
    3470              : //{
    3471              : //      return static_cast<DTC_DebugType>((0xFFFF & val.has_value()) ? *val : ReadRegister_(DTC_Register_DebugPacketType));
    3472              : // }
    3473              : 
    3474              : /// <summary>
    3475              : /// Formats the register's current value for register dumps
    3476              : /// </summary>
    3477              : /// <returns>RegisterFormatter object containing register information</returns>
    3478              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationDebugPacketType()
    3479              : //{
    3480              : //      auto form = CreateFormatter(DTC_Register_DebugPacketType);
    3481              : //      form.description = "CFO Emulation Debug Packet Type";
    3482              : //      form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3483              : //      form.vals.push_back(std::string("Debug Mode: [") + (ReadDebugPacketMode(form.value) ? "x" : " ") + "]");
    3484              : //      std::stringstream o;
    3485              : //      o << "Debug Packet Type: 0x" << std::hex << ReadCFOEmulationDebugType(form.value);
    3486              : //      form.vals.push_back(o.str());
    3487              : //      return form;
    3488              : // }
    3489              : 
    3490              : // RX Packet Count Error Flags Register
    3491              : /// <summary>
    3492              : /// Read the RX Packet Count Error flag for the given link
    3493              : /// </summary>
    3494              : /// <param name="link">Link to read</param>
    3495              : /// <returns>Whether the RX Packet Count Error flag is set on the link</returns>
    3496            0 : bool DTCLib::DTC_Registers::ReadRXPacketCountErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3497              : {
    3498            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
    3499            0 :         return dataSet[link];
    3500              : }
    3501              : 
    3502              : /// <summary>
    3503              : /// Clear the RX Packet Count Error flag for the given link
    3504              : /// </summary>
    3505              : /// <param name="link">Link to clear</param>
    3506            0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags(DTC_Link_ID const& link)
    3507              : {
    3508            0 :         std::bitset<32> dataSet;
    3509            0 :         dataSet[link] = true;
    3510            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
    3511            0 : }
    3512              : 
    3513              : /// <summary>
    3514              : /// Clear all RX Packet Count Error Flags
    3515              : /// </summary>
    3516            0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags()
    3517              : {
    3518            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
    3519            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
    3520            0 : }
    3521              : 
    3522              : /// <summary>
    3523              : /// Formats the register's current value for register dumps
    3524              : /// </summary>
    3525              : /// <returns>RegisterFormatter object containing register information</returns>
    3526            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXPacketCountErrorFlags()
    3527              : {
    3528            0 :         auto form = CreateFormatter(DTC_Register_RXPacketCountErrorFlags);
    3529            0 :         form.description = "RX Packet Count Error Flags";
    3530            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3531            0 :         for (auto r : DTC_ROC_Links)
    3532            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    3533            0 :                                                         (ReadRXPacketCountErrorFlags(r, form.value) ? "x" : " ") + "]");
    3534            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadRXPacketCountErrorFlags(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    3535            0 :         form.vals.push_back(std::string("EVB:    [") + (ReadRXPacketCountErrorFlags(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    3536            0 :         return form;
    3537            0 : }
    3538              : 
    3539              : // Detector Emulator DMA Count Register
    3540              : /// <summary>
    3541              : /// Set the number of DMAs that the Detector Emulator will generate when enabled
    3542              : /// </summary>
    3543              : /// <param name="count">The number of DMAs that the Detector Emulator will generate when enabled</param>
    3544            0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMACount(uint32_t count)
    3545              : {
    3546            0 :         WriteRegister_(count, DTC_Register_DetEmulation_DMACount);
    3547            0 : }
    3548              : 
    3549              : /// <summary>
    3550              : /// Read the number of DMAs that the Detector Emulator will generate
    3551              : /// </summary>
    3552              : /// <returns>The number of DMAs that the Detector Emulator will generate</returns>
    3553            0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMACount(std::optional<uint32_t> val)
    3554              : {
    3555            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DMACount);
    3556              : }
    3557              : 
    3558              : /// <summary>
    3559              : /// Formats the register's current value for register dumps
    3560              : /// </summary>
    3561              : /// <returns>RegisterFormatter object containing register information</returns>
    3562            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMACount()
    3563              : {
    3564            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DMACount);
    3565            0 :         form.description = "DetEmu DMA Count";
    3566            0 :         std::stringstream o;
    3567            0 :         o << "0x" << std::hex << ReadDetectorEmulationDMACount(form.value);
    3568            0 :         form.vals.push_back(o.str());
    3569            0 :         return form;
    3570            0 : }
    3571              : 
    3572              : // Detector Emulator DMA Delay Counter Register
    3573              : /// <summary>
    3574              : /// Set the delay between DMAs in Detector Emulator mode
    3575              : /// </summary>
    3576              : /// <param name="count">Delay between DMAs in Detector Emulation mode, in 4ns ticks</param>
    3577            0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMADelayCount(uint32_t count)
    3578              : {
    3579            0 :         WriteRegister_(count, DTC_Register_DetEmulation_DelayCount);
    3580            0 : }
    3581              : 
    3582              : /// <summary>
    3583              : /// Read the amount of the delay between DMAs in Detector Emulator mode
    3584              : /// </summary>
    3585              : /// <returns>The amount of the delay between DMAs in Detector Emulator mode, in 4ns ticks</returns>
    3586            0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMADelayCount(std::optional<uint32_t> val)
    3587              : {
    3588            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DelayCount);
    3589              : }
    3590              : 
    3591              : /// <summary>
    3592              : /// Formats the register's current value for register dumps
    3593              : /// </summary>
    3594              : /// <returns>RegisterFormatter object containing register information</returns>
    3595            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMADelayCount()
    3596              : {
    3597            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DelayCount);
    3598            0 :         form.description = "DetEmu DMA Delay Count";
    3599            0 :         std::stringstream o;
    3600            0 :         o << "0x" << std::hex << ReadDetectorEmulationDMADelayCount(form.value);
    3601            0 :         form.vals.push_back(o.str());
    3602            0 :         return form;
    3603            0 : }
    3604              : 
    3605              : /// <summary>
    3606              : /// Enable Detector Emulator Mode. This sends all DMA writes to DMA channel 0 (DAQ) to DDR memory
    3607              : /// </summary>
    3608            0 : void DTCLib::DTC_Registers::EnableDetectorEmulatorMode()
    3609              : {
    3610            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3611            0 :         data[0] = 1;
    3612            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3613            0 : }
    3614              : 
    3615              : /// <summary>
    3616              : /// Disable sending DMA data to DDR memory
    3617              : /// </summary>
    3618            0 : void DTCLib::DTC_Registers::DisableDetectorEmulatorMode()
    3619              : {
    3620            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3621            0 :         data[0] = 0;
    3622            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3623            0 : }
    3624              : 
    3625              : /// <summary>
    3626              : /// Read whether writes to DMA Channel 0 will be loaded into DDR memory
    3627              : /// </summary>
    3628              : /// <returns>Whether the Detector Emulator Mode bit is set</returns>
    3629            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorMode(std::optional<uint32_t> val)
    3630              : {
    3631            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
    3632            0 :         return data[0];
    3633              : }
    3634              : 
    3635              : /// <summary>
    3636              : /// Enable the Detector Emulator (Playback Mode)
    3637              : /// This assumes that data has been loaded into DDR memory using DMA Channel 0 before enabling.
    3638              : /// </summary>
    3639            0 : void DTCLib::DTC_Registers::EnableDetectorEmulator()
    3640              : {
    3641            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3642            0 :         data[1] = 1;
    3643            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3644            0 : }
    3645              : 
    3646              : /// <summary>
    3647              : /// Turn off the Detector Emulator (Playback Mode)
    3648              : /// </summary>
    3649            0 : void DTCLib::DTC_Registers::DisableDetectorEmulator()
    3650              : {
    3651            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control1);
    3652            0 :         data[1] = 1;
    3653            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control1);
    3654            0 : }
    3655              : 
    3656              : /// <summary>
    3657              : /// Read whether the Detector Emulator is enabled
    3658              : /// </summary>
    3659              : /// <returns>Whether the Detector Emulator is enabled</returns>
    3660            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnable(std::optional<uint32_t> val)
    3661              : {
    3662            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
    3663            0 :         return data[1];
    3664              : }
    3665              : 
    3666              : /// <summary>
    3667              : /// Read whether a Detector Emulator Disable operation is in progress
    3668              : /// </summary>
    3669              : /// <returns>Whether the Detector Emulator Enable Clear bit is set</returns>
    3670            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnableClear(std::optional<uint32_t> val)
    3671              : {
    3672            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control1);
    3673            0 :         return data[1];
    3674              : }
    3675              : 
    3676              : /// <summary>
    3677              : /// Clear the "Detector Emulator In Use" virtual register
    3678              : /// </summary>
    3679            0 : void DTCLib::DTC_Registers::ClearDetectorEmulatorInUse()
    3680              : {
    3681            0 :         DisableDetectorEmulator();
    3682            0 :         DisableDetectorEmulatorMode();
    3683            0 :         ResetDDRWriteAddress();
    3684            0 :         ResetDDRReadAddress();
    3685            0 :         SetDDRDataLocalStartAddress(0);
    3686            0 :         SetDDRDataLocalEndAddress(0x7000000);
    3687            0 :         usingDetectorEmulator_ = false;
    3688            0 : }
    3689              : 
    3690              : /// <summary>
    3691              : /// Formats the register's current value for register dumps
    3692              : /// </summary>
    3693              : /// <returns>RegisterFormatter object containing register information</returns>
    3694            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl0()
    3695              : {
    3696            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_Control0);
    3697            0 :         form.description = "Detector Emulation Control 0";
    3698            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3699            0 :         form.vals.push_back(std::string("Detector Emulation Enable: [") + (ReadDetectorEmulatorEnable(form.value) ? "x" : " ") + "]");
    3700            0 :         form.vals.push_back(std::string("Detector Emulation Mode:   [") + (ReadDetectorEmulatorMode(form.value) ? "x" : " ") + "]");
    3701            0 :         return form;
    3702            0 : }
    3703              : 
    3704              : /// <summary>
    3705              : /// Formats the register's current value for register dumps
    3706              : /// </summary>
    3707              : /// <returns>RegisterFormatter object containing register information</returns>
    3708            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl1()
    3709              : {
    3710            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_Control1);
    3711            0 :         form.description = "Detector Emulation Control 1";
    3712            0 :         form.vals.push_back(std::string("Detector Emulation Enable Clear: [") +
    3713            0 :                                                 (ReadDetectorEmulatorEnableClear(form.value) ? "x" : " ") + "]");
    3714            0 :         return form;
    3715            0 : }
    3716              : 
    3717              : // DDR Event Data Local Start Address Register
    3718              : /// <summary>
    3719              : /// Set the DDR Data Start Address
    3720              : /// DDR Addresses are in bytes and must be 64-bit aligned
    3721              : /// </summary>
    3722              : /// <param name="address">Start address for the DDR data section</param>
    3723            0 : void DTCLib::DTC_Registers::SetDDRDataLocalStartAddress(uint32_t address)
    3724              : {
    3725            0 :         WriteRegister_(address, DTC_Register_DetEmulation_DataStartAddress);
    3726            0 : }
    3727              : 
    3728              : /// <summary>
    3729              : /// Read the DDR Data Start Address
    3730              : /// </summary>
    3731              : /// <returns>The current DDR data start address</returns>
    3732            0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalStartAddress(std::optional<uint32_t> val)
    3733              : {
    3734            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataStartAddress);
    3735              : }
    3736              : 
    3737              : /// <summary>
    3738              : /// Formats the register's current value for register dumps
    3739              : /// </summary>
    3740              : /// <returns>RegisterFormatter object containing register information</returns>
    3741            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalStartAddress()
    3742              : {
    3743            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DataStartAddress);
    3744            0 :         form.description = "DDR Event Data Local Start Address";
    3745            0 :         std::stringstream o;
    3746            0 :         o << "0x" << std::hex << ReadDDRDataLocalStartAddress(form.value);
    3747            0 :         form.vals.push_back(o.str());
    3748            0 :         return form;
    3749            0 : }
    3750              : 
    3751              : // DDR Event Data Local End Address Register
    3752              : /// <summary>
    3753              : /// Set the end address for the DDR data section
    3754              : /// DDR Addresses are in bytes and must be 64-bit aligned
    3755              : /// </summary>
    3756              : /// <param name="address"></param>
    3757            0 : void DTCLib::DTC_Registers::SetDDRDataLocalEndAddress(uint32_t address)
    3758              : {
    3759            0 :         WriteRegister_(address, DTC_Register_DetEmulation_DataEndAddress);
    3760            0 : }
    3761              : 
    3762              : /// <summary>
    3763              : /// Read the current end address for the DDR Data section
    3764              : /// </summary>
    3765              : /// <returns>End address for the DDR data section</returns>
    3766            0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalEndAddress(std::optional<uint32_t> val)
    3767              : {
    3768            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataEndAddress);
    3769              : }
    3770              : 
    3771              : /// <summary>
    3772              : /// Formats the register's current value for register dumps
    3773              : /// </summary>
    3774              : /// <returns>RegisterFormatter object containing register information</returns>
    3775            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalEndAddress()
    3776              : {
    3777            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DataEndAddress);
    3778            0 :         form.description = "DDR Event Data Local End Address";
    3779            0 :         std::stringstream o;
    3780            0 :         o << "0x" << std::hex << ReadDDRDataLocalEndAddress(form.value);
    3781            0 :         form.vals.push_back(o.str());
    3782            0 :         return form;
    3783            0 : }
    3784              : 
    3785            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulatorInterpacketDelay(std::optional<uint32_t> val)
    3786              : {
    3787            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_DataRequestDelay);
    3788              : }
    3789              : 
    3790            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulatorInterpacketDelay()
    3791              : {
    3792            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_DataRequestDelay);
    3793            0 :         form.description = "CFO Emulator Data Request Interpacket Delay";
    3794            0 :         std::stringstream o;
    3795            0 :         o << std::dec << ReadCFOEmulatorInterpacketDelay(form.value) << " * 5 ns";
    3796            0 :         form.vals.push_back(o.str());
    3797            0 :         return form;
    3798            0 : }
    3799              : 
    3800              : /// <summary>
    3801              : /// Read the current maximum Ethernet payload size
    3802              : /// </summary>
    3803              : /// <returns>The current maximum Ethernet payload size</returns>
    3804            0 : uint32_t DTCLib::DTC_Registers::ReadEthernetPayloadSize(std::optional<uint32_t> val)
    3805              : {
    3806            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EthernetFramePayloadSize);
    3807              : }
    3808              : 
    3809              : /// <summary>
    3810              : /// Set the maximum Ethernet payload size, in bytes. Maximum is 1492 bytes.
    3811              : /// </summary>
    3812              : /// <param name="size">Maximum Ethernet payload size, in bytes</param>
    3813            0 : void DTCLib::DTC_Registers::SetEthernetPayloadSize(uint32_t size)
    3814              : {
    3815            0 :         if (size > 1492)
    3816              :         {
    3817            0 :                 size = 1492;
    3818              :         }
    3819            0 :         WriteRegister_(size, DTC_Register_EthernetFramePayloadSize);
    3820            0 : }
    3821              : 
    3822              : /// <summary>
    3823              : /// Formats the register's current value for register dumps
    3824              : /// </summary>
    3825              : /// <returns>RegisterFormatter object containing register information</returns>
    3826            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEthernetPayloadSize()
    3827              : {
    3828            0 :         auto form = CreateFormatter(DTC_Register_EthernetFramePayloadSize);
    3829            0 :         form.description = "Ethernet Frame Payload Max Size";
    3830            0 :         std::stringstream o;
    3831            0 :         o << std::dec << ReadEthernetPayloadSize(form.value) << " bytes";
    3832            0 :         form.vals.push_back(o.str());
    3833            0 :         return form;
    3834            0 : }
    3835              : 
    3836            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulation40MHzMarkerInterval(std::optional<uint32_t> val)
    3837              : {
    3838            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3839              : }
    3840              : 
    3841            0 : void DTCLib::DTC_Registers::SetCFOEmulation40MHzMarkerInterval(uint32_t interval)
    3842              : {
    3843            0 :         WriteRegister_(interval, DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3844            0 : }
    3845              : 
    3846            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulation40MHzMarkerInterval()
    3847              : {
    3848            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3849            0 :         form.description = "CFO Emulation 40MHz Marker Interval";
    3850            0 :         std::stringstream o;
    3851            0 :         o << "0x" << std::hex << ReadCFOEmulation40MHzMarkerInterval(form.value);
    3852            0 :         form.vals.push_back(o.str());
    3853            0 :         return form;
    3854            0 : }
    3855              : 
    3856              : // bool DTCLib::DTC_Registers::ReadCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3857              : // {
    3858              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(DTC_Register_CFOMarkerEnables);
    3859              : //      return dataSet[link + 8];
    3860              : // }
    3861              : 
    3862              : // void DTCLib::DTC_Registers::SetCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, bool enable)
    3863              : // {
    3864              : //      std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
    3865              : //      data[link + 8] = enable;
    3866              : //      WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
    3867              : // }
    3868              : 
    3869            0 : bool DTCLib::DTC_Registers::ReadCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3870              : {
    3871            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOMarkerEnables);
    3872            0 :         return dataSet[link];
    3873              : }
    3874              : 
    3875            0 : void DTCLib::DTC_Registers::SetCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, bool enable)
    3876              : {
    3877            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
    3878            0 :         if (link == DTC_Link_ALL)
    3879              :         {
    3880            0 :                 for (uint8_t i = 0; i < 6; ++i)  // just ROC links
    3881            0 :                         data[i] = enable;
    3882              :         }
    3883              :         else
    3884            0 :                 data[link] = enable;
    3885            0 :         WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
    3886            0 : }
    3887              : 
    3888            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFO40MHzClockMarkerEnables()
    3889              : {
    3890            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
    3891            0 :         form.description = "CFO Emulation Marker Enables";
    3892              :         // form.vals.push_back("        [Event Start, 40 MHz]");
    3893            0 :         form.vals.push_back("        [40 MHz Clock Marker]");
    3894            0 :         for (auto r : DTC_ROC_Links)
    3895            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    3896              :                                                         // (ReadCFOEventStartMarkerEnable(r, form.value) ? "x" : " ") + "," +
    3897            0 :                                                         (ReadCFO40MHzClockMarkerEnable(r, form.value) ? "x" : " ") + "]");
    3898            0 :         return form;
    3899            0 : }
    3900              : 
    3901            0 : uint8_t DTCLib::DTC_Registers::ReadROCCommaLimit(std::optional<uint32_t> val)
    3902              : {
    3903            0 :         return static_cast<uint8_t>(val.has_value() ? *val : ReadRegister_(DTC_Register_ROCFinishThreshold));
    3904              : }
    3905              : 
    3906            0 : void DTCLib::DTC_Registers::SetROCCommaLimit(uint8_t limit)
    3907              : {
    3908            0 :         uint32_t data = ReadRegister_(DTC_Register_ROCFinishThreshold) & 0xFFFFFF00;
    3909            0 :         data += limit;
    3910            0 :         WriteRegister_(data, DTC_Register_ROCFinishThreshold);
    3911            0 : }
    3912              : 
    3913            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCFinishThreshold()
    3914              : {
    3915            0 :         auto form = CreateFormatter(DTC_Register_ROCFinishThreshold);
    3916            0 :         form.description = "ROC Finish Threshold";
    3917            0 :         std::stringstream o;
    3918            0 :         o << "ROC Comma Limit: 0x" << std::hex << static_cast<int>(ReadROCCommaLimit(form.value));
    3919            0 :         form.vals.push_back(o.str());
    3920            0 :         return form;
    3921            0 : }
    3922              : 
    3923            0 : bool DTCLib::DTC_Registers::ReadTXPRBSForceError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3924              : {
    3925            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl));
    3926            0 :         return dataSet[link + 24];
    3927              : }
    3928              : 
    3929            0 : void DTCLib::DTC_Registers::SetTXPRBSForceError(DTC_Link_ID const& link)
    3930              : {
    3931            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
    3932            0 :         dataSet[link + 24] = 1;
    3933            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
    3934            0 : }
    3935              : 
    3936            0 : void DTCLib::DTC_Registers::ClearTXPRBSForceError(DTC_Link_ID const& link)
    3937              : {
    3938            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
    3939            0 :         dataSet[link + 24] = 0;
    3940            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
    3941            0 : }
    3942              : 
    3943            0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadTXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3944              : {
    3945            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl);
    3946            0 :         auto masked = (data >> link) & 0x7;
    3947            0 :         return static_cast<DTC_PRBSMode>(masked);
    3948              : }
    3949              : 
    3950            0 : void DTCLib::DTC_Registers::SetTXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
    3951              : {
    3952            0 :         auto data = ReadRegister_(DTC_Register_TXPRBSControl);
    3953            0 :         auto masked = data & ~(0x7 << link);
    3954            0 :         auto newMode = static_cast<uint32_t>(mode);
    3955            0 :         WriteRegister_(masked + (newMode << link), DTC_Register_TXPRBSControl);
    3956            0 : }
    3957              : 
    3958            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESTXPRBSControl()
    3959              : {
    3960            0 :         auto form = CreateFormatter(DTC_Register_TXPRBSControl);
    3961            0 :         form.description = "SERDES TX PRBS Control";
    3962            0 :         form.vals.push_back("       ([Force Error, Mode])");
    3963            0 :         for (auto r : DTC_ROC_Links)
    3964            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    3965            0 :                                                         (ReadTXPRBSForceError(r, form.value) ? "x" : " ") + "," +
    3966            0 :                                                         (DTC_PRBSModeConverter(ReadTXPRBSMode(r, form.value)).toString()) + "]");
    3967            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadTXPRBSForceError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    3968            0 :                                                 (DTC_PRBSModeConverter(ReadTXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
    3969            0 :         return form;
    3970            0 : }
    3971              : 
    3972            0 : bool DTCLib::DTC_Registers::ReadRXPRBSError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3973              : {
    3974            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl));
    3975            0 :         return dataSet[link + 24];
    3976              : }
    3977              : 
    3978            0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadRXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3979              : {
    3980            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl);
    3981            0 :         auto masked = (data >> link) & 0x7;
    3982            0 :         return static_cast<DTC_PRBSMode>(masked);
    3983              : }
    3984              : 
    3985            0 : void DTCLib::DTC_Registers::SetRXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
    3986              : {
    3987            0 :         auto data = ReadRegister_(DTC_Register_RXPRBSControl);
    3988            0 :         auto masked = data & ~(0x7 << link);
    3989            0 :         auto newMode = static_cast<uint32_t>(mode);
    3990            0 :         WriteRegister_(masked + (newMode << link), DTC_Register_RXPRBSControl);
    3991            0 : }
    3992              : 
    3993            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSControl()
    3994              : {
    3995            0 :         auto form = CreateFormatter(DTC_Register_RXPRBSControl);
    3996            0 :         form.description = "SERDES RX PRBS Control";
    3997            0 :         form.vals.push_back("       ([Error, Mode])");
    3998            0 :         for (auto r : DTC_ROC_Links)
    3999            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    4000            0 :                                                         (ReadRXPRBSError(r, form.value) ? "x" : " ") + "," +
    4001            0 :                                                         (DTC_PRBSModeConverter(ReadRXPRBSMode(r, form.value)).toString()) + "]");
    4002            0 :         form.vals.push_back(std::string("CFO:    [") +
    4003            0 :                                                 (ReadRXPRBSError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    4004            0 :                                                 (DTC_PRBSModeConverter(ReadRXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
    4005            0 :         return form;
    4006            0 : }
    4007              : 
    4008            0 : bool DTCLib::DTC_Registers::ReadEventModeTableEnable(std::optional<uint32_t> val)
    4009              : {
    4010            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4011            0 :         return dataSet[16];
    4012              : }
    4013              : 
    4014            0 : void DTCLib::DTC_Registers::SetEventModeTableEnable()
    4015              : {
    4016            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4017            0 :         dataSet[16] = 1;
    4018            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
    4019            0 : }
    4020              : 
    4021            0 : void DTCLib::DTC_Registers::ClearEventModeTableEnable()
    4022              : {
    4023            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4024            0 :         dataSet[16] = 0;
    4025            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
    4026            0 : }
    4027              : 
    4028            0 : uint8_t DTCLib::DTC_Registers::ReadEventModeLookupByteSelect(std::optional<uint32_t> val)
    4029              : {
    4030            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl);
    4031            0 :         auto masked = (data) & 0x7;
    4032            0 :         return static_cast<uint8_t>(masked);
    4033              : }
    4034              : 
    4035            0 : void DTCLib::DTC_Registers::SetEventModeLookupByteSelect(uint8_t byte)
    4036              : {
    4037            0 :         auto data = ReadRegister_(DTC_Register_EventModeLookupTableControl);
    4038            0 :         auto masked = data & 0xFFF8;
    4039            0 :         WriteRegister_(masked + (byte & 0x7), DTC_Register_EventModeLookupTableControl);
    4040            0 : }
    4041              : 
    4042            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventModeLookupTableControl()
    4043              : {
    4044            0 :         auto form = CreateFormatter(DTC_Register_EventModeLookupTableControl);
    4045            0 :         form.description = "Event Mode Lookup Table Control";
    4046            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4047            0 :         form.vals.push_back(std::string("Enabled:  [") +
    4048            0 :                                                 (ReadEventModeTableEnable(form.value) ? "x" : " ") + "]");
    4049            0 :         form.vals.push_back(std::string("Byte:          [") +
    4050            0 :                                                 std::to_string(ReadEventModeLookupByteSelect(form.value)) + "]");
    4051            0 :         return form;
    4052            0 : }
    4053              : 
    4054            0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestComplete(std::optional<uint32_t> val)
    4055              : {
    4056            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
    4057            0 :         return dataSet[8];
    4058              : }
    4059              : 
    4060            0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestError(std::optional<uint32_t> val)
    4061              : {
    4062            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
    4063            0 :         return dataSet[0];
    4064              : }
    4065              : 
    4066            0 : void DTCLib::DTC_Registers::ClearDDRMemoryTestError()
    4067              : {
    4068            0 :         WriteRegister_(1, DTC_Register_DD3TestRegister);
    4069            0 : }
    4070              : 
    4071            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRMemoryTestRegister()
    4072              : {
    4073            0 :         auto form = CreateFormatter(DTC_Register_DD3TestRegister);
    4074            0 :         form.description = "DDR3 Memory Test";
    4075            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4076            0 :         form.vals.push_back(std::string("Test Complete:  [") +
    4077            0 :                                                 (ReadDDRMemoryTestComplete(form.value) ? "x" : " ") + "]");
    4078            0 :         form.vals.push_back(std::string("Error:          [") +
    4079            0 :                                                 (ReadDDRMemoryTestError(form.value) ? "x" : " ") + "]");
    4080            0 :         return form;
    4081            0 : }
    4082              : 
    4083              : // SERDES Serial Inversion Enable Register
    4084              : /// <summary>
    4085              : /// Read the Invert SERDES RX Input bit
    4086              : /// </summary>
    4087              : /// <param name="link">Link to read</param>
    4088              : /// <returns>Whether the Invert SERDES RX Input bit is set</returns>
    4089            0 : bool DTCLib::DTC_Registers::ReadInvertSERDESRXInput(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4090              : {
    4091            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4092            0 :         return data[link + 8];
    4093              : }
    4094              : /// <summary>
    4095              : /// Set the Invert SERDES RX Input bit
    4096              : /// </summary>
    4097              : /// <param name="link">Link to set</param>
    4098              : /// <param name="invert">Whether to invert</param>
    4099            0 : void DTCLib::DTC_Registers::SetInvertSERDESRXInput(DTC_Link_ID const& link, bool invert)
    4100              : {
    4101            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4102            0 :         data[link + 8] = invert;
    4103            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
    4104            0 : }
    4105              : /// <summary>
    4106              : /// Read the Invert SERDES TX Output bit
    4107              : /// </summary>
    4108              : /// <param name="link">Link to read</param>
    4109              : /// <returns>Whether the Invert SERDES TX Output bit is set</returns>
    4110            0 : bool DTCLib::DTC_Registers::ReadInvertSERDESTXOutput(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4111              : {
    4112            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4113            0 :         return data[link];
    4114              : }
    4115              : /// <summary>
    4116              : /// Set the Invert SERDES TX Output bit
    4117              : /// </summary>
    4118              : /// <param name="link">Link to set</param>
    4119              : /// <param name="invert">Whether to invert</param>
    4120            0 : void DTCLib::DTC_Registers::SetInvertSERDESTXOutput(DTC_Link_ID const& link, bool invert)
    4121              : {
    4122            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4123            0 :         data[link] = invert;
    4124            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
    4125            0 : }
    4126              : /// <summary>
    4127              : /// Formats the register's current value for register dumps
    4128              : /// </summary>
    4129              : /// <returns>RegisterFormatter object containing register information</returns>
    4130            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESSerialInversionEnable()
    4131              : {
    4132            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    4133            0 :         form.description = "SERDES Serial Inversion Enable";
    4134            0 :         form.vals.push_back("       ([Input, Output])");
    4135            0 :         for (auto r : DTC_ROC_Links)
    4136            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    4137            0 :                                                         (ReadInvertSERDESRXInput(r, form.value) ? "x" : " ") + "," +
    4138            0 :                                                         (ReadInvertSERDESTXOutput(r, form.value) ? "x" : " ") + "]");
    4139            0 :         form.vals.push_back(std::string("CFO:    [") +
    4140            0 :                                                 (ReadInvertSERDESRXInput(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    4141            0 :                                                 (ReadInvertSERDESTXOutput(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    4142              : 
    4143            0 :         return form;
    4144            0 : }
    4145              : 
    4146              : // Jitter Attenuator CSR Register
    4147              : /// <summary>
    4148              : /// Read the value of the Jitter Attenuator Select
    4149              : /// </summary>
    4150              : /// <returns>Jitter Attenuator Select value</returns>
    4151            0 : std::bitset<2> DTCLib::DTC_Registers::ReadJitterAttenuatorSelect(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR); }
    4152              : 
    4153              : /// <summary>
    4154              : /// Set the Jitter Attenuator Select bits. JA reset only needed after a power cycle
    4155              : /// </summary>
    4156              : /// <param name="data">Value to set</param>
    4157            0 : void DTCLib::DTC_Registers::SetJitterAttenuatorSelect(std::bitset<2> data, bool alsoResetJA /* = false */) { CFOandDTC_Registers::SetJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR, data, alsoResetJA); }
    4158              : 
    4159              : /// <summary>
    4160              : /// Read the Jitter Attenuator Reset bit
    4161              : /// </summary>
    4162              : /// <returns>Value of the Jitter Attenuator Reset bit</returns>
    4163            0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorReset(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorReset(DTC_Register_JitterAttenuatorCSR, val); }
    4164            0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorLocked(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorLocked(DTC_Register_JitterAttenuatorCSR, val); }
    4165              : 
    4166              : /// <summary>
    4167              : /// Reset the Jitter Attenuator
    4168              : /// </summary>
    4169            0 : void DTCLib::DTC_Registers::ResetJitterAttenuator() { CFOandDTC_Registers::ResetJitterAttenuator(DTC_Register_JitterAttenuatorCSR); }
    4170              : 
    4171              : /// <summary>
    4172              : /// Formats the register's current value for register dumps
    4173              : /// </summary>
    4174              : /// <returns>RegisterFormatter object containing register information</returns>
    4175            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorCSR() { return CFOandDTC_Registers::FormatJitterAttenuatorCSR(DTC_Register_JitterAttenuatorCSR); }
    4176              : 
    4177              : // SFP IIC Registers
    4178              : 
    4179              : /// <summary>
    4180              : /// Read the Reset bit of the SFP IIC Bus
    4181              : /// </summary>
    4182              : /// <returns>Reset bit value</returns>
    4183            0 : bool DTCLib::DTC_Registers::ReadSFPIICInterfaceReset(std::optional<uint32_t> val)
    4184              : {
    4185            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SFP_IICBusControl));
    4186            0 :         return dataSet[31];
    4187              : }
    4188              : /// <summary>
    4189              : /// Reset the SFP IIC Bus
    4190              : /// </summary>
    4191            0 : void DTCLib::DTC_Registers::ResetSFPIICInterface()
    4192              : {
    4193            0 :         auto bs = std::bitset<32>();
    4194            0 :         bs[31] = 1;
    4195            0 :         WriteRegister_(bs.to_ulong(), DTC_Register_SFP_IICBusControl);
    4196            0 :         while (ReadSFPIICInterfaceReset())
    4197              :         {
    4198            0 :                 usleep(1000);
    4199              :         }
    4200            0 : }
    4201              : /// <summary>
    4202              : /// Write a value to the SFP IIC Bus
    4203              : /// </summary>
    4204              : /// <param name="device">Device address</param>
    4205              : /// <param name="address">Register address</param>
    4206              : /// <param name="data">Data to write</param>
    4207            0 : void DTCLib::DTC_Registers::WriteSFPIICInterface(uint8_t device, uint8_t address, uint8_t data)
    4208              : {
    4209            0 :         uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16) + (data << 8);
    4210            0 :         WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
    4211            0 :         WriteRegister_(0x1, DTC_Register_SFP_IICBusHigh);
    4212            0 :         while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x1)
    4213              :         {
    4214            0 :                 usleep(1000);
    4215              :         }
    4216            0 : }
    4217              : /// <summary>
    4218              : /// Read a value from the SFP IIC Bus
    4219              : /// </summary>
    4220              : /// <param name="device">Device address</param>
    4221              : /// <param name="address">Register address</param>
    4222              : /// <returns>Value of register</returns>
    4223            0 : uint8_t DTCLib::DTC_Registers::ReadSFPIICInterface(uint8_t device, uint8_t address)
    4224              : {
    4225            0 :         uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16);
    4226            0 :         WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
    4227            0 :         WriteRegister_(0x2, DTC_Register_SFP_IICBusHigh);
    4228            0 :         while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x2)
    4229              :         {
    4230            0 :                 usleep(1000);
    4231              :         }
    4232            0 :         auto data = ReadRegister_(DTC_Register_SFP_IICBusLow);
    4233            0 :         return static_cast<uint8_t>(data);
    4234              : }
    4235              : 
    4236              : /// <summary>
    4237              : /// Formats the register's current value for register dumps
    4238              : /// </summary>
    4239              : /// <returns>RegisterFormatter object containing register information</returns>
    4240            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICControl()
    4241              : {
    4242            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusControl);
    4243            0 :         form.description = "SFP Oscillator IIC Bus Control";
    4244            0 :         form.vals.push_back(std::string("Reset:  [") + (ReadSFPIICInterfaceReset(form.value) ? "x" : " ") + "]");
    4245            0 :         return form;
    4246            0 : }
    4247              : /// <summary>
    4248              : /// Formats the register's current value for register dumps
    4249              : /// </summary>
    4250              : /// <returns>RegisterFormatter object containing register information</returns>
    4251            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterLow()
    4252              : {
    4253            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusLow);
    4254            0 :         form.description = "SFP Oscillator IIC Bus Low";
    4255            0 :         form.vals.push_back("");  // translation
    4256            0 :         auto data = form.value;
    4257            0 :         std::ostringstream s1, s2, s3, s4;
    4258            0 :         s1 << "Device:     " << std::showbase << std::hex << ((data & 0xFF000000) >> 24);
    4259            0 :         form.vals.push_back(s1.str());
    4260            0 :         s2 << "ASFPess:    " << std::showbase << std::hex << ((data & 0xFF0000) >> 16);
    4261            0 :         form.vals.push_back(s2.str());
    4262            0 :         s3 << "Write Data: " << std::showbase << std::hex << ((data & 0xFF00) >> 8);
    4263            0 :         form.vals.push_back(s3.str());
    4264            0 :         s4 << "Read Data:  " << std::showbase << std::hex << (data & 0xFF);
    4265            0 :         form.vals.push_back(s4.str());
    4266            0 :         return form;
    4267            0 : }
    4268              : /// <summary>
    4269              : /// Formats the register's current value for register dumps
    4270              : /// </summary>
    4271              : /// <returns>RegisterFormatter object containing register information</returns>
    4272            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterHigh()
    4273              : {
    4274            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusHigh);
    4275            0 :         auto data = form.value;
    4276            0 :         form.description = "SFP Oscillator IIC Bus High";
    4277            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4278            0 :         form.vals.push_back(std::string("Write:  [") + (data & 0x1 ? "x" : " ") + "]");
    4279            0 :         form.vals.push_back(std::string("Read:   [") + (data & 0x2 ? "x" : " ") + "]");
    4280            0 :         return form;
    4281            0 : }
    4282              : 
    4283            0 : uint32_t DTCLib::DTC_Registers::ReadRetransmitRequestCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4284              : {
    4285            0 :         switch (link)
    4286              :         {
    4287            0 :                 case DTC_Link_0:
    4288            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link0);
    4289            0 :                 case DTC_Link_1:
    4290            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link1);
    4291            0 :                 case DTC_Link_2:
    4292            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link2);
    4293            0 :                 case DTC_Link_3:
    4294            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link3);
    4295            0 :                 case DTC_Link_4:
    4296            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link4);
    4297            0 :                 case DTC_Link_5:
    4298            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link5);
    4299            0 :                 default: {
    4300            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4301            0 :                         __SS_THROW__;
    4302            0 :                 }
    4303              :         }
    4304              : }
    4305            0 : void DTCLib::DTC_Registers::ClearRetransmitRequestCount(DTC_Link_ID const& link)
    4306              : {
    4307            0 :         switch (link)
    4308              :         {
    4309            0 :                 case DTC_Link_0:
    4310            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link0);
    4311            0 :                         break;
    4312            0 :                 case DTC_Link_1:
    4313            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link1);
    4314            0 :                         break;
    4315            0 :                 case DTC_Link_2:
    4316            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link2);
    4317            0 :                         break;
    4318            0 :                 case DTC_Link_3:
    4319            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link3);
    4320            0 :                         break;
    4321            0 :                 case DTC_Link_4:
    4322            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link4);
    4323            0 :                         break;
    4324            0 :                 case DTC_Link_5:
    4325            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link5);
    4326            0 :                         break;
    4327            0 :                 default: {
    4328            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4329            0 :                         __SS_THROW__;
    4330            0 :                 }
    4331              :         }
    4332            0 : }
    4333              : 
    4334              : /// <summary>
    4335              : /// Formats the register's current value for register dumps
    4336              : /// </summary>
    4337              : /// <returns>RegisterFormatter object containing register information</returns>
    4338            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink0()
    4339              : {
    4340            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link0);
    4341            0 :         form.description = "ROC Retransmit Request Count Link 0";
    4342            0 :         std::stringstream o;
    4343            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_0, form.value);
    4344            0 :         form.vals.push_back(o.str());
    4345            0 :         return form;
    4346            0 : }
    4347              : 
    4348              : /// <summary>
    4349              : /// Formats the register's current value for register dumps
    4350              : /// </summary>
    4351              : /// <returns>RegisterFormatter object containing register information</returns>
    4352            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink1()
    4353              : {
    4354            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link1);
    4355            0 :         form.description = "ROC Retransmit Request Count Link 1";
    4356            0 :         std::stringstream o;
    4357            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_1, form.value);
    4358            0 :         form.vals.push_back(o.str());
    4359            0 :         return form;
    4360            0 : }
    4361              : 
    4362              : /// <summary>
    4363              : /// Formats the register's current value for register dumps
    4364              : /// </summary>
    4365              : /// <returns>RegisterFormatter object containing register information</returns>
    4366            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink2()
    4367              : {
    4368            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link2);
    4369            0 :         form.description = "ROC Retransmit Request Count Link 2";
    4370            0 :         std::stringstream o;
    4371            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_2, form.value);
    4372            0 :         form.vals.push_back(o.str());
    4373            0 :         return form;
    4374            0 : }
    4375              : 
    4376              : /// <summary>
    4377              : /// Formats the register's current value for register dumps
    4378              : /// </summary>
    4379              : /// <returns>RegisterFormatter object containing register information</returns>
    4380            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink3()
    4381              : {
    4382            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link3);
    4383            0 :         form.description = "ROC Retransmit Request Count Link 3";
    4384            0 :         std::stringstream o;
    4385            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_3, form.value);
    4386            0 :         form.vals.push_back(o.str());
    4387            0 :         return form;
    4388            0 : }
    4389              : 
    4390              : /// <summary>
    4391              : /// Formats the register's current value for register dumps
    4392              : /// </summary>
    4393              : /// <returns>RegisterFormatter object containing register information</returns>
    4394            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink4()
    4395              : {
    4396            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link4);
    4397            0 :         form.description = "ROC Retransmit Request Count Link 4";
    4398            0 :         std::stringstream o;
    4399            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_4, form.value);
    4400            0 :         form.vals.push_back(o.str());
    4401            0 :         return form;
    4402            0 : }
    4403              : 
    4404              : /// <summary>
    4405              : /// Formats the register's current value for register dumps
    4406              : /// </summary>
    4407              : /// <returns>RegisterFormatter object containing register information</returns>
    4408            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink5()
    4409              : {
    4410            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link5);
    4411            0 :         form.description = "ROC Retransmit Request Count Link 5";
    4412            0 :         std::stringstream o;
    4413            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_5, form.value);
    4414            0 :         form.vals.push_back(o.str());
    4415            0 :         return form;
    4416            0 : }
    4417              : 
    4418              : // Missed CFO Packet Count Registers
    4419              : /**
    4420              :  * @brief Read the missed CFO Packet Count for the given link
    4421              :  * @param link Link to read
    4422              :  * @returns Number of missed CFO packets for the given link, or 0 if an invalid link is given
    4423              :  */
    4424            0 : uint32_t DTCLib::DTC_Registers::ReadMissedCFOPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4425              : {
    4426            0 :         switch (link)
    4427              :         {
    4428            0 :                 case DTC_Link_0:
    4429            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link0);
    4430            0 :                 case DTC_Link_1:
    4431            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link1);
    4432            0 :                 case DTC_Link_2:
    4433            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link2);
    4434            0 :                 case DTC_Link_3:
    4435            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link3);
    4436            0 :                 case DTC_Link_4:
    4437            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link4);
    4438            0 :                 case DTC_Link_5:
    4439            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link5);
    4440            0 :                 default: {
    4441            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4442            0 :                         __SS_THROW__;
    4443            0 :                 }
    4444              :         }
    4445              : }
    4446              : 
    4447              : /// <summary>
    4448              : /// Clears the Missed CFO Packet Count for the given link
    4449              : /// </summary>
    4450              : /// <param name="link">Link to clear</param>
    4451            0 : void DTCLib::DTC_Registers::ClearMissedCFOPacketCount(DTC_Link_ID const& link)
    4452              : {
    4453            0 :         switch (link)
    4454              :         {
    4455            0 :                 case DTC_Link_0:
    4456            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link0);
    4457            0 :                         break;
    4458            0 :                 case DTC_Link_1:
    4459            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link1);
    4460            0 :                         break;
    4461            0 :                 case DTC_Link_2:
    4462            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link2);
    4463            0 :                         break;
    4464            0 :                 case DTC_Link_3:
    4465            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link3);
    4466            0 :                         break;
    4467            0 :                 case DTC_Link_4:
    4468            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link4);
    4469            0 :                         break;
    4470            0 :                 case DTC_Link_5:
    4471            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link5);
    4472            0 :                         break;
    4473            0 :                 default: {
    4474            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4475            0 :                         __SS_THROW__;
    4476            0 :                 }
    4477              :         }
    4478            0 : }
    4479              : 
    4480              : /// <summary>
    4481              : /// Formats the register's current value for register dumps
    4482              : /// </summary>
    4483              : /// <returns>RegisterFormatter object containing register information</returns>
    4484            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink0()
    4485              : {
    4486            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link0);
    4487            0 :         form.description = "Missed CFO Packet Count Link 0";
    4488            0 :         std::stringstream o;
    4489            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_0, form.value);
    4490            0 :         form.vals.push_back(o.str());
    4491            0 :         return form;
    4492            0 : }
    4493              : 
    4494              : /// <summary>
    4495              : /// Formats the register's current value for register dumps
    4496              : /// </summary>
    4497              : /// <returns>RegisterFormatter object containing register information</returns>
    4498            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink1()
    4499              : {
    4500            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link1);
    4501            0 :         form.description = "Missed CFO Packet Count Link 1";
    4502            0 :         std::stringstream o;
    4503            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_1, form.value);
    4504            0 :         form.vals.push_back(o.str());
    4505            0 :         return form;
    4506            0 : }
    4507              : 
    4508              : /// <summary>
    4509              : /// Formats the register's current value for register dumps
    4510              : /// </summary>
    4511              : /// <returns>RegisterFormatter object containing register information</returns>
    4512            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink2()
    4513              : {
    4514            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link2);
    4515            0 :         form.description = "Missed CFO Packet Count Link 2";
    4516            0 :         std::stringstream o;
    4517            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_2, form.value);
    4518            0 :         form.vals.push_back(o.str());
    4519            0 :         return form;
    4520            0 : }
    4521              : 
    4522              : /// <summary>
    4523              : /// Formats the register's current value for register dumps
    4524              : /// </summary>
    4525              : /// <returns>RegisterFormatter object containing register information</returns>
    4526            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink3()
    4527              : {
    4528            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link3);
    4529            0 :         form.description = "Missed CFO Packet Count Link 3";
    4530            0 :         std::stringstream o;
    4531            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_3, form.value);
    4532            0 :         form.vals.push_back(o.str());
    4533            0 :         return form;
    4534            0 : }
    4535              : 
    4536              : /// <summary>
    4537              : /// Formats the register's current value for register dumps
    4538              : /// </summary>
    4539              : /// <returns>RegisterFormatter object containing register information</returns>
    4540            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink4()
    4541              : {
    4542            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link4);
    4543            0 :         form.description = "Missed CFO Packet Count Link 4";
    4544            0 :         std::stringstream o;
    4545            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_4, form.value);
    4546            0 :         form.vals.push_back(o.str());
    4547            0 :         return form;
    4548            0 : }
    4549              : 
    4550              : /// <summary>
    4551              : /// Formats the register's current value for register dumps
    4552              : /// </summary>
    4553              : /// <returns>RegisterFormatter object containing register information</returns>
    4554            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink5()
    4555              : {
    4556            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link5);
    4557            0 :         form.description = "Missed CFO Packet Count Link 5";
    4558            0 :         std::stringstream o;
    4559            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_5, form.value);
    4560            0 :         form.vals.push_back(o.str());
    4561            0 :         return form;
    4562            0 : }
    4563              : 
    4564              : // Local Fragment Drop Count Register
    4565              : /// <summary>
    4566              : /// Reads the current value of the Local Fragment Drop Counter
    4567              : /// </summary>
    4568              : /// <returns>The number of fragments dropped by the DTC</returns>
    4569            0 : uint32_t DTCLib::DTC_Registers::ReadLocalFragmentDropCount(std::optional<uint32_t> val)
    4570              : {
    4571            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_LocalFragmentDropCount);
    4572              : }
    4573              : 
    4574              : /// <summary>
    4575              : /// Clears the Local Fragment Drop Counter
    4576              : /// </summary>
    4577            0 : void DTCLib::DTC_Registers::ClearLocalFragmentDropCount() { WriteRegister_(1, DTC_Register_LocalFragmentDropCount); }
    4578              : 
    4579              : /// <summary>
    4580              : /// Formats the register's current value for register dumps
    4581              : /// </summary>
    4582              : /// <returns>RegisterFormatter object containing register information</returns>
    4583            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLocalFragmentDropCount()
    4584              : {
    4585            0 :         auto form = CreateFormatter(DTC_Register_LocalFragmentDropCount);
    4586            0 :         form.description = "Local Data Fragment Drop Count";
    4587            0 :         std::stringstream o;
    4588            0 :         o << std::dec << ReadLocalFragmentDropCount(form.value);
    4589            0 :         form.vals.push_back(o.str());
    4590            0 :         return form;
    4591            0 : }
    4592              : 
    4593            0 : uint32_t DTCLib::DTC_Registers::ReadEVBSubEventReceiveTimer(std::optional<uint32_t> val)
    4594              : {
    4595            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSubEventReceiveTimerPreset);
    4596              : }
    4597              : 
    4598            0 : void DTCLib::DTC_Registers::SetEVBSubEventReceiveTimer(uint32_t timer)
    4599              : {
    4600            0 :         WriteRegister_(timer, DTC_Register_EVBSubEventReceiveTimerPreset);
    4601            0 : }
    4602              : 
    4603            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSubEventReceiveTimer()
    4604              : {
    4605            0 :         auto form = CreateFormatter(DTC_Register_EVBSubEventReceiveTimerPreset);
    4606            0 :         form.description = "EVB SubEvent Receive Timer (*4ns)";
    4607            0 :         std::stringstream o;
    4608            0 :         o << std::dec << ReadEVBSubEventReceiveTimer(form.value);
    4609            0 :         form.vals.push_back(o.str());
    4610            0 :         return form;
    4611            0 : }
    4612              : 
    4613              : // EVB SERDES PRBS Register
    4614              : /// <summary>
    4615              : /// Determine if an error was detected in the EVB SERDES PRBS module
    4616              : /// </summary>
    4617              : /// <returns>True if error condition was detected, false otherwise</returns>
    4618            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSErrorFlag(std::optional<uint32_t> val)
    4619              : {
    4620            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4621            0 :         return regVal[31];
    4622              : }
    4623              : 
    4624              : /// <summary>
    4625              : /// Read the EVB SERDES TX PRBS Select
    4626              : /// </summary>
    4627              : /// <returns>Value of the EVB SERDES TX PRBS Select</returns>
    4628            0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESTXPRBSSEL(std::optional<uint32_t> val)
    4629              : {
    4630            0 :         uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x7000) >> 12);
    4631            0 :         return regVal;
    4632              : }
    4633              : 
    4634              : /// <summary>
    4635              : /// Set the EVB SERDES TX PRBS Select
    4636              : /// </summary>
    4637              : /// <param name="byte">Value of the EVB SERDES TX PRBS Select</param>
    4638            0 : void DTCLib::DTC_Registers::SetEVBSERDESTXPRBSSEL(uint8_t byte)
    4639              : {
    4640            0 :         uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFF8FFF);
    4641            0 :         regVal += ((byte & 0x7) << 12);
    4642            0 :         WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
    4643            0 : }
    4644              : 
    4645              : /// <summary>
    4646              : /// Read the EVB SERDES RX PRBS Select
    4647              : /// </summary>
    4648              : /// <returns>Value of the EVB SERDES RX PRBS Select</returns>
    4649            0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESRXPRBSSEL(std::optional<uint32_t> val)
    4650              : {
    4651            0 :         uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x700) >> 8);
    4652            0 :         return regVal;
    4653              : }
    4654              : 
    4655              : /// <summary>
    4656              : /// Set the EVB SERDES RX PRBS Select
    4657              : /// </summary>
    4658              : /// <param name="byte">Value of the EVB SERDES RX PRBS Select</param>
    4659            0 : void DTCLib::DTC_Registers::SetEVBSERDESRXPRBSSEL(uint8_t byte)
    4660              : {
    4661            0 :         uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFFF8FF);
    4662            0 :         regVal += ((byte & 0x7) << 8);
    4663            0 :         WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
    4664            0 : }
    4665              : 
    4666              : /// <summary>
    4667              : /// Read the state of the EVB SERDES PRBS Force Error bit
    4668              : /// </summary>
    4669              : /// <returns>True if the EVB SERDES PRBS Force Error bit is high</returns>
    4670            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSForceError(std::optional<uint32_t> val)
    4671              : {
    4672            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4673            0 :         return regVal[1];
    4674              : }
    4675              : 
    4676              : /// <summary>
    4677              : /// Set the EVB SERDES PRBS Force Error bit
    4678              : /// </summary>
    4679              : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
    4680            0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSForceError(bool flag)
    4681              : {
    4682            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4683            0 :         regVal[1] = flag;
    4684            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4685            0 : }
    4686              : 
    4687              : /// <summary>
    4688              : /// Toggle the EVB SERDES PRBS Force Error bit (make it true if false, false if true)
    4689              : /// </summary>
    4690            0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSForceError()
    4691              : {
    4692            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4693            0 :         regVal.flip(0);
    4694            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4695            0 : }
    4696              : 
    4697              : /// <summary>
    4698              : /// Read the state of the EVB SERDES PRBS Reset bit
    4699              : /// </summary>
    4700              : /// <returns>True if the EVB SERDES PRBS Reset bit is high</returns>
    4701            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSReset(std::optional<uint32_t> val)
    4702              : {
    4703            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4704            0 :         return regVal[0];
    4705              : }
    4706              : 
    4707              : /// <summary>
    4708              : /// Set the EVB SERDES PRBS Reset bit
    4709              : /// </summary>
    4710              : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
    4711            0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSReset(bool flag)
    4712              : {
    4713            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4714            0 :         regVal[0] = flag;
    4715            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4716            0 : }
    4717              : 
    4718              : /// <summary>
    4719              : /// Toggle the EVB SERDES PRBS Reset bit (make it true if false, false if true)
    4720              : /// </summary>
    4721            0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSReset()
    4722              : {
    4723            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4724            0 :         regVal.flip(0);
    4725            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4726            0 : }
    4727              : 
    4728              : /// <summary>
    4729              : /// Formats the register's current value for register dumps
    4730              : /// </summary>
    4731              : /// <returns>RegisterFormatter object containing register information</returns>
    4732            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESPRBSControl()
    4733              : {
    4734            0 :         auto form = CreateFormatter(DTC_Register_EVBSERDESPRBSControlStatus);
    4735            0 :         form.description = "EVB SERDES PRBS Control / Status";
    4736            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4737            0 :         form.vals.push_back(std::string("PRBS Error: [") + (ReadEVBSERDESPRBSErrorFlag(form.value) ? "x" : " ") + "]");
    4738            0 :         std::stringstream o;
    4739            0 :         o << "EVB SERDES TX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESTXPRBSSEL(form.value));
    4740            0 :         form.vals.push_back(o.str());
    4741            0 :         o.str("");
    4742            0 :         o.clear();
    4743            0 :         o << "EVB SERDES RX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESRXPRBSSEL(form.value));
    4744            0 :         form.vals.push_back(std::string("PRBS Force Error: [") + (ReadEVBSERDESPRBSForceError(form.value) ? "x" : " ") + "]");
    4745            0 :         form.vals.push_back(std::string("PRBS Reset: [") + (ReadEVBSERDESPRBSReset(form.value) ? "x" : " ") + "]");
    4746              : 
    4747            0 :         return form;
    4748            0 : }
    4749              : 
    4750              : // Event Builder Error Register
    4751              : /// <summary>
    4752              : /// Read the Event Builder SubEvent Receiver Flags Buffer Error bit
    4753              : /// </summary>
    4754              : /// <returns>Value of the bit</returns>
    4755            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_SubEventReceiverFlagsBufferError(std::optional<uint32_t> val)
    4756              : {
    4757            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4758            0 :         return data[24];
    4759              : }
    4760              : /// <summary>
    4761              : /// Read the Event Builder Ethernet Input FIFO Full bit
    4762              : /// </summary>
    4763              : /// <returns>Value of the bit</returns>
    4764            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_EthernetInputFIFOFull(std::optional<uint32_t> val)
    4765              : {
    4766            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4767            0 :         return data[16];
    4768              : }
    4769              : /// <summary>
    4770              : /// Read the Event Builder Link Error bit
    4771              : /// </summary>
    4772              : /// <returns>Value of the bit</returns>
    4773            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LinkError(std::optional<uint32_t> val)
    4774              : {
    4775            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4776            0 :         return data[9];
    4777              : }
    4778              : /// <summary>
    4779              : /// Read the Event Builder TX Packet Error bit
    4780              : /// </summary>
    4781              : /// <returns>Value of the bit</returns>
    4782            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TXPacketError(std::optional<uint32_t> val)
    4783              : {
    4784            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4785            0 :         return data[8];
    4786              : }
    4787              : /// <summary>
    4788              : /// Read the Event Builder Local Data Pointer FIFO Queue Error bit
    4789              : /// </summary>
    4790              : /// <returns>Value of the bit</returns>
    4791            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LocalDataPointerFIFOQueueError(std::optional<uint32_t> val)
    4792              : {
    4793            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4794            0 :         return data[1];
    4795              : }
    4796              : /// <summary>
    4797              : /// Read the Event Builder Transmit DMA Byte Count FIFO Full bit
    4798              : /// </summary>
    4799              : /// <returns>Value of the bit</returns>
    4800            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TransmitDMAByteCountFIFOFull(std::optional<uint32_t> val)
    4801              : {
    4802            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4803            0 :         return data[0];
    4804              : }
    4805              : /// <summary>
    4806              : /// Formats the register's current value for register dumps
    4807              : /// </summary>
    4808              : /// <returns>RegisterFormatter object containing register information</returns>
    4809            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventBuilderErrorRegister()
    4810              : {
    4811            0 :         auto form = CreateFormatter(DTC_Register_EventBuilderErrorFlags);
    4812            0 :         form.description = "Event Builder Error Flags";
    4813            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4814            0 :         form.vals.push_back(std::string("Sub-Event Received Flags Buffer Error: [") +
    4815            0 :                                                 (ReadEventBuilder_SubEventReceiverFlagsBufferError(form.value) ? "x" : " ") + "]");
    4816            0 :         form.vals.push_back(std::string("Input FIFO Full:                       [") +
    4817            0 :                                                 (ReadEventBuilder_EthernetInputFIFOFull(form.value) ? "x" : " ") + "]");
    4818            0 :         form.vals.push_back(std::string("Link Error:                            [") +
    4819            0 :                                                 (ReadEventBuilder_LinkError(form.value) ? "x" : " ") + "]");
    4820            0 :         form.vals.push_back(std::string("TX Packet Error:                       [") +
    4821            0 :                                                 (ReadEventBuilder_TXPacketError(form.value) ? "x" : " ") + "]");
    4822            0 :         form.vals.push_back(std::string("Local Data Pointer FIFO Queue Error:   [") +
    4823            0 :                                                 (ReadEventBuilder_LocalDataPointerFIFOQueueError(form.value) ? "x" : " ") + "]");
    4824            0 :         form.vals.push_back(std::string("Transmit DMA Byte Count FIFO Full:     [") +
    4825            0 :                                                 (ReadEventBuilder_TransmitDMAByteCountFIFOFull(form.value) ? "x" : " ") + "]");
    4826            0 :         return form;
    4827            0 : }
    4828              : 
    4829              : // SERDES VFIFO Error Register
    4830              : /// <summary>
    4831              : /// Read the SERDES VFIFO Egress FIFO Full bit
    4832              : /// </summary>
    4833              : /// <returns>Value of the bit</returns>
    4834            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
    4835              : {
    4836            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4837            0 :         return data[10];
    4838              : }
    4839              : /// <summary>
    4840              : /// Read the SERDES VFIFO Ingress FIFO Full bit
    4841              : /// </summary>
    4842              : /// <returns>Value of the bit</returns>
    4843            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
    4844              : {
    4845            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4846            0 :         return data[9];
    4847              : }
    4848              : /// <summary>
    4849              : /// Read the SERDES VFIFO Event Byte Count Total Error bit
    4850              : /// </summary>
    4851              : /// <returns>Value of the bit</returns>
    4852            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
    4853              : {
    4854            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4855            0 :         return data[8];
    4856              : }
    4857              : /// <summary>
    4858              : /// Read the SERDES VFIFO Last Word Written Timeout Error bit
    4859              : /// </summary>
    4860              : /// <returns>Value of the bit</returns>
    4861            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_LastWordWrittenTimeoutError(std::optional<uint32_t> val)
    4862              : {
    4863            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4864            0 :         return data[2];
    4865              : }
    4866              : /// <summary>
    4867              : /// Read the SERDES VFIFO Fragment Count Error bit
    4868              : /// </summary>
    4869              : /// <returns>Value of the bit</returns>
    4870            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_FragmentCountError(std::optional<uint32_t> val)
    4871              : {
    4872            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4873            0 :         return data[1];
    4874              : }
    4875              : /// <summary>
    4876              : /// Read the SERDES VFIFO DDR Full Error bit
    4877              : /// </summary>
    4878              : /// <returns>Value of the bit</returns>
    4879            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_DDRFullError(std::optional<uint32_t> val)
    4880              : {
    4881            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4882            0 :         return data[0];
    4883              : }
    4884              : /// <summary>
    4885              : /// Formats the register's current value for register dumps
    4886              : /// </summary>
    4887              : /// <returns>RegisterFormatter object containing register information</returns>
    4888            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESVFIFOError()
    4889              : {
    4890            0 :         auto form = CreateFormatter(DTC_Register_InputBufferErrorFlags);
    4891            0 :         form.description = "SERDES VFIFO Error Flags";
    4892            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4893            0 :         form.vals.push_back(std::string("Egress FIFO Full:             [") + (ReadSERDESVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
    4894              :                                                 "]");
    4895            0 :         form.vals.push_back(std::string("Ingress FIFO Full:            [") + (ReadSERDESVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
    4896              :                                                 "]");
    4897            0 :         form.vals.push_back(std::string("Event Byte Count Total Error: [") +
    4898            0 :                                                 (ReadSERDESVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
    4899            0 :         form.vals.push_back(std::string("Last Word Written Timeout:    [") +
    4900            0 :                                                 (ReadSERDESVFIFO_LastWordWrittenTimeoutError(form.value) ? "x" : " ") + "]");
    4901            0 :         form.vals.push_back(std::string("Fragment count Error:         [") +
    4902            0 :                                                 (ReadSERDESVFIFO_FragmentCountError(form.value) ? "x" : " ") + "]");
    4903            0 :         form.vals.push_back(std::string("DDR Full Error:               [") + (ReadSERDESVFIFO_DDRFullError(form.value) ? "x" : " ") +
    4904              :                                                 "]");
    4905            0 :         return form;
    4906            0 : }
    4907              : 
    4908              : // PCI VFIFO Error Register
    4909              : /// <summary>
    4910              : /// Read the PCI VIFO DDR Full bit
    4911              : /// </summary>
    4912              : /// <returns>Value of the bit</returns>
    4913            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_DDRFull(std::optional<uint32_t> val)
    4914              : {
    4915            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4916            0 :         return data[12];
    4917              : }
    4918              : /// <summary>
    4919              : /// Read the PCI VIFO Memmory Mapped Write Complete FIFO Full bit
    4920              : /// </summary>
    4921              : /// <returns>Value of the bit</returns>
    4922            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(std::optional<uint32_t> val)
    4923              : {
    4924            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4925            0 :         return data[11];
    4926              : }
    4927              : /// <summary>
    4928              : /// Read the PCI VIFO PCI Write Event FIFO Full bit
    4929              : /// </summary>
    4930              : /// <returns>Value of the bit</returns>
    4931            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_PCIWriteEventFIFOFull(std::optional<uint32_t> val)
    4932              : {
    4933            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4934            0 :         return data[10];
    4935              : }
    4936              : /// <summary>
    4937              : /// Read the PCI VIFO Local Data Pointer FIFO Full bit
    4938              : /// </summary>
    4939              : /// <returns>Value of the bit</returns>
    4940            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_LocalDataPointerFIFOFull(std::optional<uint32_t> val)
    4941              : {
    4942            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4943            0 :         return data[9];
    4944              : }
    4945              : /// <summary>
    4946              : /// Read the PCI VIFO Egress FIFO Full bit
    4947              : /// </summary>
    4948              : /// <returns>Value of the bit</returns>
    4949            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
    4950              : {
    4951            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4952            0 :         return data[8];
    4953              : }
    4954              : /// <summary>
    4955              : /// Read the PCI VIFO RX Buffer Select FIFO Full bit
    4956              : /// </summary>
    4957              : /// <returns>Value of the bit</returns>
    4958            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_RXBufferSelectFIFOFull(std::optional<uint32_t> val)
    4959              : {
    4960            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4961            0 :         return data[2];
    4962              : }
    4963              : /// <summary>
    4964              : /// Read the PCI VIFO Ingress FIFO Full bit
    4965              : /// </summary>
    4966              : /// <returns>Value of the bit</returns>
    4967            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
    4968              : {
    4969            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4970            0 :         return data[1];
    4971              : }
    4972              : /// <summary>
    4973              : /// Read the PCI VIFO Event Byte Count Total Error bit
    4974              : /// </summary>
    4975              : /// <returns>Value of the bit</returns>
    4976            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
    4977              : {
    4978            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4979            0 :         return data[0];
    4980              : }
    4981              : /// <summary>
    4982              : /// Formats the register's current value for register dumps
    4983              : /// </summary>
    4984              : /// <returns>RegisterFormatter object containing register information</returns>
    4985            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatPCIVFIFOError()
    4986              : {
    4987            0 :         auto form = CreateFormatter(DTC_Register_OutputBufferErrorFlags);
    4988            0 :         form.description = "PCI VFIFO Error Flags";
    4989            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4990            0 :         form.vals.push_back(std::string("DDR Full Error:               [") + (ReadPCIVFIFO_DDRFull(form.value) ? "x" : " ") + "]");
    4991            0 :         form.vals.push_back(std::string("Memmap Write Cmplt FIFO Full: [") +
    4992            0 :                                                 (ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(form.value) ? "x" : " ") + "]");
    4993            0 :         form.vals.push_back(std::string("PCI Write Event FIFO Full:    [") +
    4994            0 :                                                 (ReadPCIVFIFO_PCIWriteEventFIFOFull(form.value) ? "x" : " ") + "]");
    4995            0 :         form.vals.push_back(std::string("Local Data Pointer FIFO Full: [") +
    4996            0 :                                                 (ReadPCIVFIFO_LocalDataPointerFIFOFull(form.value) ? "x" : " ") + "]");
    4997            0 :         form.vals.push_back(std::string("Egress FIFO Full:             [") + (ReadPCIVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
    4998              :                                                 "]");
    4999            0 :         form.vals.push_back(std::string("RX Buffer Select FIFO Full:   [") +
    5000            0 :                                                 (ReadPCIVFIFO_RXBufferSelectFIFOFull(form.value) ? "x" : " ") + "]");
    5001            0 :         form.vals.push_back(std::string("Ingress FIFO Ful:             [") + (ReadPCIVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
    5002              :                                                 "]");
    5003            0 :         form.vals.push_back(std::string("Event Byte Count Total Error: [") +
    5004            0 :                                                 (ReadPCIVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
    5005            0 :         return form;
    5006            0 : }
    5007              : 
    5008              : // ROC Link Error Registers
    5009              : /// <summary>
    5010              : /// Read the Receive Data Request Sync Error bit for the given link
    5011              : /// </summary>
    5012              : /// <param name="link">Link to read</param>
    5013              : /// <returns>Value of the bit</returns>
    5014            0 : bool DTCLib::DTC_Registers::ReadROCLink_ROCDataRequestSyncError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5015              : {
    5016            0 :         std::bitset<32> data;
    5017            0 :         switch (link)
    5018              :         {
    5019            0 :                 case DTC_Link_0:
    5020            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5021            0 :                         break;
    5022            0 :                 case DTC_Link_1:
    5023            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5024            0 :                         break;
    5025            0 :                 case DTC_Link_2:
    5026            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5027            0 :                         break;
    5028            0 :                 case DTC_Link_3:
    5029            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5030            0 :                         break;
    5031            0 :                 case DTC_Link_4:
    5032            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5033            0 :                         break;
    5034            0 :                 case DTC_Link_5:
    5035            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5036            0 :                         break;
    5037            0 :                 default: {
    5038            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5039            0 :                         __SS_THROW__;
    5040            0 :                 }
    5041              :         }
    5042            0 :         return data[5];
    5043              : }
    5044              : /// <summary>
    5045              : /// Read the Receive RX Packet Count Error bit for the given link
    5046              : /// </summary>
    5047              : /// <param name="link">Link to read</param>
    5048              : /// <returns>Value of the bit</returns>
    5049            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5050              : {
    5051            0 :         std::bitset<32> data;
    5052            0 :         switch (link)
    5053              :         {
    5054            0 :                 case DTC_Link_0:
    5055            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5056            0 :                         break;
    5057            0 :                 case DTC_Link_1:
    5058            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5059            0 :                         break;
    5060            0 :                 case DTC_Link_2:
    5061            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5062            0 :                         break;
    5063            0 :                 case DTC_Link_3:
    5064            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5065            0 :                         break;
    5066            0 :                 case DTC_Link_4:
    5067            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5068            0 :                         break;
    5069            0 :                 case DTC_Link_5:
    5070            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5071            0 :                         break;
    5072            0 :                 default: {
    5073            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5074            0 :                         __SS_THROW__;
    5075            0 :                 }
    5076              :         }
    5077            0 :         return data[4];
    5078              : }
    5079              : /// <summary>
    5080              : /// Read the Receive RX Packet Error bit for the given link
    5081              : /// </summary>
    5082              : /// <param name="link">Link to read</param>
    5083              : /// <returns>Value of the bit</returns>
    5084            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5085              : {
    5086            0 :         std::bitset<32> data;
    5087            0 :         switch (link)
    5088              :         {
    5089            0 :                 case DTC_Link_0:
    5090            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5091            0 :                         break;
    5092            0 :                 case DTC_Link_1:
    5093            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5094            0 :                         break;
    5095            0 :                 case DTC_Link_2:
    5096            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5097            0 :                         break;
    5098            0 :                 case DTC_Link_3:
    5099            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5100            0 :                         break;
    5101            0 :                 case DTC_Link_4:
    5102            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5103            0 :                         break;
    5104            0 :                 case DTC_Link_5:
    5105            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5106            0 :                         break;
    5107            0 :                 default: {
    5108            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5109            0 :                         __SS_THROW__;
    5110            0 :                 }
    5111              :         }
    5112            0 :         return data[3];
    5113              : }
    5114              : /// <summary>
    5115              : /// Read the Receive RX Packet CRC Error bit for the given link
    5116              : /// </summary>
    5117              : /// <param name="link">Link to read</param>
    5118              : /// <returns>Value of the bit</returns>
    5119            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5120              : {
    5121            0 :         std::bitset<32> data;
    5122            0 :         switch (link)
    5123              :         {
    5124            0 :                 case DTC_Link_0:
    5125            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5126            0 :                         break;
    5127            0 :                 case DTC_Link_1:
    5128            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5129            0 :                         break;
    5130            0 :                 case DTC_Link_2:
    5131            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5132            0 :                         break;
    5133            0 :                 case DTC_Link_3:
    5134            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5135            0 :                         break;
    5136            0 :                 case DTC_Link_4:
    5137            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5138            0 :                         break;
    5139            0 :                 case DTC_Link_5:
    5140            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5141            0 :                         break;
    5142            0 :                 default: {
    5143            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5144            0 :                         __SS_THROW__;
    5145            0 :                 }
    5146              :         }
    5147            0 :         return data[2];
    5148              : }
    5149              : /// <summary>
    5150              : /// Read the Receive Data Pending Timeout Error bit for the given link
    5151              : /// </summary>
    5152              : /// <param name="link">Link to read</param>
    5153              : /// <returns>Value of the bit</returns>
    5154            0 : bool DTCLib::DTC_Registers::ReadROCLink_DataPendingTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5155              : {
    5156            0 :         std::bitset<32> data;
    5157            0 :         switch (link)
    5158              :         {
    5159            0 :                 case DTC_Link_0:
    5160            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5161            0 :                         break;
    5162            0 :                 case DTC_Link_1:
    5163            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5164            0 :                         break;
    5165            0 :                 case DTC_Link_2:
    5166            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5167            0 :                         break;
    5168            0 :                 case DTC_Link_3:
    5169            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5170            0 :                         break;
    5171            0 :                 case DTC_Link_4:
    5172            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5173            0 :                         break;
    5174            0 :                 case DTC_Link_5:
    5175            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5176            0 :                         break;
    5177            0 :                 default: {
    5178            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5179            0 :                         __SS_THROW__;
    5180            0 :                 }
    5181              :         }
    5182            0 :         return data[1];
    5183              : }
    5184              : /// <summary>
    5185              : /// Read the Receive Data Packet Count Error bit for the given link
    5186              : /// </summary>
    5187              : /// <param name="link">Link to read</param>
    5188              : /// <returns>Value of the bit</returns>
    5189            0 : bool DTCLib::DTC_Registers::ReadROCLink_ReceiveDataPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5190              : {
    5191            0 :         std::bitset<32> data;
    5192            0 :         switch (link)
    5193              :         {
    5194            0 :                 case DTC_Link_0:
    5195            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5196            0 :                         break;
    5197            0 :                 case DTC_Link_1:
    5198            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5199            0 :                         break;
    5200            0 :                 case DTC_Link_2:
    5201            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5202            0 :                         break;
    5203            0 :                 case DTC_Link_3:
    5204            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5205            0 :                         break;
    5206            0 :                 case DTC_Link_4:
    5207            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5208            0 :                         break;
    5209            0 :                 case DTC_Link_5:
    5210            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5211            0 :                         break;
    5212            0 :                 default: {
    5213            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5214            0 :                         __SS_THROW__;
    5215            0 :                 }
    5216              :         }
    5217            0 :         return data[0];
    5218              : }
    5219              : /// <summary>
    5220              : /// Formats the register's current value for register dumps
    5221              : /// </summary>
    5222              : /// <returns>RegisterFormatter object containing register information</returns>
    5223            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink0Error()
    5224              : {
    5225            0 :         auto form = CreateFormatter(DTC_Register_Link0ErrorFlags);
    5226            0 :         form.description = "ROC Link 0 Error";
    5227            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5228            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5229            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5230            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5231            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5232            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5233            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5234            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5235            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5236            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5237            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5238            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5239            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5240            0 :         return form;
    5241            0 : }
    5242              : /// <summary>
    5243              : /// Formats the register's current value for register dumps
    5244              : /// </summary>
    5245              : /// <returns>RegisterFormatter object containing register information</returns>
    5246            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink1Error()
    5247              : {
    5248            0 :         auto form = CreateFormatter(DTC_Register_Link1ErrorFlags);
    5249            0 :         form.description = "ROC Link 1 Error";
    5250            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5251            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5252            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5253            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5254            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5255            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5256            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5257            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5258            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5259            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5260            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5261            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5262            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5263            0 :         return form;
    5264            0 : }
    5265              : /// <summary>
    5266              : /// Formats the register's current value for register dumps
    5267              : /// </summary>
    5268              : /// <returns>RegisterFormatter object containing register information</returns>
    5269            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink2Error()
    5270              : {
    5271            0 :         auto form = CreateFormatter(DTC_Register_Link2ErrorFlags);
    5272            0 :         form.description = "ROC Link 2 Error";
    5273            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5274            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5275            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5276            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5277            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5278            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5279            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5280            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5281            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5282            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5283            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5284            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5285            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5286            0 :         return form;
    5287            0 : }
    5288              : /// <summary>
    5289              : /// Formats the register's current value for register dumps
    5290              : /// </summary>
    5291              : /// <returns>RegisterFormatter object containing register information</returns>
    5292            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink3Error()
    5293              : {
    5294            0 :         auto form = CreateFormatter(DTC_Register_Link3ErrorFlags);
    5295            0 :         form.description = "ROC Link 3 Error";
    5296            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5297            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5298            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5299            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5300            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5301            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5302            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5303            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5304            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5305            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5306            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5307            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5308            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5309            0 :         return form;
    5310            0 : }
    5311              : /// <summary>
    5312              : /// Formats the register's current value for register dumps
    5313              : /// </summary>
    5314              : /// <returns>RegisterFormatter object containing register information</returns>
    5315            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink4Error()
    5316              : {
    5317            0 :         auto form = CreateFormatter(DTC_Register_Link4ErrorFlags);
    5318            0 :         form.description = "ROC Link 4 Error";
    5319            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5320            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5321            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5322            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5323            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5324            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5325            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5326            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5327            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5328            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5329            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5330            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5331            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5332            0 :         return form;
    5333            0 : }
    5334              : /// <summary>
    5335              : /// Formats the register's current value for register dumps
    5336              : /// </summary>
    5337              : /// <returns>RegisterFormatter object containing register information</returns>
    5338            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink5Error()
    5339              : {
    5340            0 :         auto form = CreateFormatter(DTC_Register_Link5ErrorFlags);
    5341            0 :         form.description = "ROC Link 5 Error";
    5342            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5343            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5344            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5345            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5346            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5347            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5348            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5349            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5350            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5351            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5352            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5353            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5354            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5355            0 :         return form;
    5356            0 : }
    5357              : 
    5358              : // CFO Link Error Register
    5359              : /// <summary>
    5360              : /// Formats the register's current value for register dumps
    5361              : /// </summary>
    5362              : /// <returns>RegisterFormatter object containing register information</returns>
    5363            0 : uint32_t DTCLib::DTC_Registers::ReadCFOLinkErrorRegister()
    5364              : {
    5365            0 :         return ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5366              : }  // end ReadCFOLinkErrorRegister()
    5367              : 
    5368              : /// @brief Measured CFO marker sample position at bits [18:16]
    5369            0 : int DTCLib::DTC_Registers::ReadCFOMeasuredMarkerPosition(std::optional<uint32_t> val)
    5370              : {
    5371            0 :         uint32_t value = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5372            0 :         return (value >> 16) & 7;
    5373              : }  // end ReadCFOMeasuredMarkerPosition()
    5374              : 
    5375              : /// @brief Implied CFO sample offset for the measured marker position.
    5376              : ///        Legal values are -2 -1 0 1 2 (if measured value is 4 3 2 1 0, respectively).
    5377            0 : int DTCLib::DTC_Registers::ReadCFOImpliedMarkerOffset(std::optional<uint32_t> val)
    5378              : {
    5379            0 :         return 2 - ReadCFOMeasuredMarkerPosition(val);
    5380              : }  // end ReadCFOImpliedMarkerOffset()
    5381              : 
    5382              : /// @brief bit 9 - Event Start marker tx error at CFO Interface
    5383            0 : bool DTCLib::DTC_Registers::ReadCFOEventStartMarkerTxError(std::optional<uint32_t> val)
    5384              : {
    5385            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5386            0 :         return data[9];
    5387              : }  // end ReadCFOEventStartMarkerTxError()
    5388              : 
    5389              : /// @brief bit 10 - Clock marker tx error at CFO Interface
    5390            0 : bool DTCLib::DTC_Registers::ReadCFOClockMarkerTxError(std::optional<uint32_t> val)
    5391              : {
    5392            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5393            0 :         return data[10];
    5394              : }  // end ReadCFOClockMarkerTxError()
    5395              : 
    5396              : /// @brief bit 11 - RTF 40MHz clock phase has shifted
    5397            0 : bool DTCLib::DTC_Registers::ReadCFORTF40MHzPhaseShiftError(std::optional<uint32_t> val)
    5398              : {
    5399            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5400            0 :         return data[11];
    5401              : }  // end ReadCFORTF40MHzPhaseShiftError()
    5402              : 
    5403              : /// @brief bit 12 - Illegal marker timing in RTF 40MHz clock count
    5404            0 : bool DTCLib::DTC_Registers::ReadCFOIllegalMarkerTimingError(std::optional<uint32_t> val)
    5405              : {
    5406            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5407            0 :         return data[12];
    5408              : }  // end ReadCFOIllegalMarkerTimingError()
    5409              : 
    5410              : /// @brief bit 13 - Moving data from CFO rx to tx clock domain has marker corruption at "external" CFO Interface
    5411            0 : bool DTCLib::DTC_Registers::ReadCFORxToTxDataCorruptionError(std::optional<uint32_t> val)
    5412              : {
    5413            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5414            0 :         return data[13];
    5415              : }  // end ReadCFORxToTxDataCorruptionError()
    5416              : 
    5417            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOLinkError()
    5418              : {
    5419            0 :         auto form = CreateFormatter(DTC_Register_CFOLinkErrorFlags);
    5420            0 :         form.description = "CFO Link Settings & Error Flags";
    5421            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5422              : 
    5423            0 :         form.vals.push_back(std::string("CFO Event Start Marker tx Error:     [") +
    5424            0 :                                                 (ReadCFOEventStartMarkerTxError(form.value) ? "x" : " ") + "]");
    5425            0 :         form.vals.push_back(std::string("CFO Clock Marker tx Error:           [") +
    5426            0 :                                                 (ReadCFOClockMarkerTxError(form.value) ? "x" : " ") + "]");
    5427            0 :         form.vals.push_back(std::string("CFO RTF 40MHz Phase Shift Error:     [") +
    5428            0 :                                                 (ReadCFORTF40MHzPhaseShiftError(form.value) ? "x" : " ") + "]");
    5429            0 :         form.vals.push_back(std::string("CFO Illegal Marker Over Link Timing: [") +
    5430            0 :                                                 (ReadCFOIllegalMarkerTimingError(form.value) ? "x" : " ") + "]");
    5431            0 :         form.vals.push_back(std::string("CFO Rx-to-Tx Data Corruption Error:  [") +
    5432            0 :                                                 (ReadCFORxToTxDataCorruptionError(form.value) ? "x" : " ") + "]");
    5433            0 :         int measuredPos = ReadCFOMeasuredMarkerPosition(form.value);
    5434            0 :         int impliedPos = ReadCFOImpliedMarkerOffset(form.value);  // legal values are -2 -1 0 1 2 (if measured value is 4 3 2 1 0, respectively)
    5435            0 :         form.vals.push_back(std::string("CFO Measured Marker position {0,4}:  [") +
    5436            0 :                                                 std::to_string(measuredPos) + "] ==> " + std::to_string(impliedPos));
    5437            0 :         form.vals.push_back(std::string("CFO Permanent Offset setting {-2,2}: [") +
    5438            0 :                                                 std::to_string(ReadCFOSamplePermanentOffset(form.value)) + "]");
    5439              : 
    5440            0 :         form.vals.push_back("");  // spacer
    5441              : 
    5442              :         // also show link enables for CFO and EVB
    5443            0 :         uint32_t val = ReadRegister_(CFOandDTC_Register_LinkEnable);
    5444            0 :         form.vals.push_back(std::string("CFO Link Rx Enabled:                 [") +
    5445            0 :                                                 (ReadLinkEnabled(DTC_Link_CFO, val).ReceiveEnable ? "x" : " ") + "]");
    5446            0 :         form.vals.push_back(std::string("CFO Link Tx Enabled:                 [") +
    5447            0 :                                                 (ReadLinkEnabled(DTC_Link_CFO, val).TransmitEnable ? "x" : " ") + "]");
    5448            0 :         form.vals.push_back(std::string("EVB Link Rx Enabled:                 [") +
    5449            0 :                                                 (ReadLinkEnabled(DTC_Link_EVB, val).ReceiveEnable ? "x" : " ") + "]");
    5450            0 :         form.vals.push_back(std::string("EVB Link Tx Enabled:                 [") +
    5451            0 :                                                 (ReadLinkEnabled(DTC_Link_EVB, val).TransmitEnable ? "x" : " ") + "]");
    5452              : 
    5453            0 :         return form;
    5454            0 : }
    5455              : 
    5456              : // Link Mux Error Register
    5457              : /// <summary>
    5458              : /// Read the DCS Mux Decode Error bit
    5459              : /// </summary>
    5460              : /// <returns>Value of the bit</returns>
    5461            0 : bool DTCLib::DTC_Registers::ReadDCSMuxDecodeError(std::optional<uint32_t> val)
    5462              : {
    5463            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
    5464            0 :         return data[1];
    5465              : }
    5466              : /// <summary>
    5467              : /// Read the Data Mux Decode Error bit
    5468              : /// </summary>
    5469              : /// <returns>Value of the bit</returns>
    5470            0 : bool DTCLib::DTC_Registers::ReadDataMuxDecodeError(std::optional<uint32_t> val)
    5471              : {
    5472            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
    5473            0 :         return data[0];
    5474              : }
    5475              : /// <summary>
    5476              : /// Formats the register's current value for register dumps
    5477              : /// </summary>
    5478              : /// <returns>RegisterFormatter object containing register information</returns>
    5479            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkMuxError()
    5480              : {
    5481            0 :         auto form = CreateFormatter(DTC_Register_LinkMuxErrorFlags);
    5482            0 :         form.description = "Link Mux Error Flags";
    5483            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5484            0 :         form.vals.push_back(std::string("DCS Mux Decode Error:  [") + (ReadDCSMuxDecodeError(form.value) ? "x" : " ") + "]");
    5485            0 :         form.vals.push_back(std::string("Data Mux Decode Error: [") + (ReadDataMuxDecodeError(form.value) ? "x" : " ") + "]");
    5486            0 :         return form;
    5487            0 : }
    5488              : 
    5489              : // SFP Control/Status Register
    5490              : /// <summary>
    5491              : /// Read the SFP Present bit
    5492              : /// </summary>
    5493              : /// <returns>Value of the bit</returns>
    5494            0 : bool DTCLib::DTC_Registers::ReadSFPPresent(std::optional<uint32_t> val)
    5495              : {
    5496            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5497            0 :         return data[31];
    5498              : }
    5499              : 
    5500              : /// <summary>
    5501              : /// Read the SFP LOS bit
    5502              : /// </summary>
    5503              : /// <returns>Value of the bit</returns>
    5504            0 : bool DTCLib::DTC_Registers::ReadSFPLOS(std::optional<uint32_t> val)
    5505              : {
    5506            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5507            0 :         return data[17];
    5508              : }
    5509              : 
    5510              : /// <summary>
    5511              : /// Read the SFP TX Fault bit
    5512              : /// </summary>
    5513              : /// <returns>Value of the bit</returns>
    5514            0 : bool DTCLib::DTC_Registers::ReadSFPTXFault(std::optional<uint32_t> val)
    5515              : {
    5516            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5517            0 :         return data[16];
    5518              : }
    5519              : 
    5520              : /// <summary>
    5521              : /// Set the SFP Rate Select bit high
    5522              : /// </summary>
    5523            0 : void DTCLib::DTC_Registers::EnableSFPRateSelect()
    5524              : {
    5525            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5526            0 :         data[1] = 1;
    5527            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5528            0 : }
    5529              : 
    5530              : /// <summary>
    5531              : /// Set the SFP Rate Select bit low
    5532              : /// </summary>
    5533            0 : void DTCLib::DTC_Registers::DisableSFPRateSelect()
    5534              : {
    5535            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5536            0 :         data[1] = 0;
    5537            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5538            0 : }
    5539              : 
    5540              : /// <summary>
    5541              : /// Read the value of the SFP Rate Select bit
    5542              : /// </summary>
    5543              : /// <returns>The value of the SFP Rate Select bit</returns>
    5544            0 : bool DTCLib::DTC_Registers::ReadSFPRateSelect(std::optional<uint32_t> val)
    5545              : {
    5546            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5547            0 :         return data[1];
    5548              : }
    5549              : 
    5550              : /// <summary>
    5551              : /// Disable SFP TX
    5552              : /// </summary>
    5553            0 : void DTCLib::DTC_Registers::DisableSFPTX()
    5554              : {
    5555            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5556            0 :         data[0] = 1;
    5557            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5558            0 : }
    5559              : 
    5560              : /// <summary>
    5561              : /// Enable SFP TX
    5562              : /// </summary>
    5563            0 : void DTCLib::DTC_Registers::EnableSFPTX()
    5564              : {
    5565            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5566            0 :         data[0] = 0;
    5567            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5568            0 : }
    5569              : 
    5570              : /// <summary>
    5571              : /// Read the SFP TX Disable bit
    5572              : /// </summary>
    5573              : /// <returns>Value of the SFP TX Disable bit</returns>
    5574            0 : bool DTCLib::DTC_Registers::ReadSFPTXDisable(std::optional<uint32_t> val)
    5575              : {
    5576            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5577            0 :         return data[0];
    5578              : }
    5579              : 
    5580              : /// <summary>
    5581              : /// Formats the register's current value for register dumps
    5582              : /// </summary>
    5583              : /// <returns>RegisterFormatter object containing register information</returns>
    5584            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPControlStatus()
    5585              : {
    5586            0 :         auto form = CreateFormatter(DTC_Register_SFPControlStatus);
    5587            0 :         form.description = "SFP Control Status";
    5588            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5589            0 :         form.vals.push_back(std::string("SFP Present:     [") + (ReadSFPPresent(form.value) ? "x" : " ") + "]");
    5590            0 :         form.vals.push_back(std::string("SFP LOS:         [") + (ReadSFPLOS(form.value) ? "x" : " ") + "]");
    5591            0 :         form.vals.push_back(std::string("SFP TX Fault:    [") + (ReadSFPTXFault(form.value) ? "x" : " ") + "]");
    5592            0 :         form.vals.push_back(std::string("SFP Rate Select: [") + (ReadSFPRateSelect(form.value) ? "x" : " ") + "]");
    5593            0 :         form.vals.push_back(std::string("SFP TX Disable:  [") + (ReadSFPTXDisable(form.value) ? "x" : " ") + "]");
    5594            0 :         return form;
    5595            0 : }
    5596              : 
    5597            0 : uint32_t DTCLib::DTC_Registers::ReadRXCDRUnlockCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5598              : {
    5599            0 :         switch (link)
    5600              :         {
    5601            0 :                 case DTC_Link_0:
    5602            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link0);
    5603            0 :                 case DTC_Link_1:
    5604            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link1);
    5605            0 :                 case DTC_Link_2:
    5606            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link2);
    5607            0 :                 case DTC_Link_3:
    5608            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link3);
    5609            0 :                 case DTC_Link_4:
    5610            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link4);
    5611            0 :                 case DTC_Link_5:
    5612            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link5);
    5613            0 :                 case DTC_Link_CFO:
    5614            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_CFOLink);
    5615            0 :                 default: {
    5616            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5617            0 :                         __SS_THROW__;
    5618            0 :                 }
    5619              :         }
    5620              : }
    5621              : 
    5622            0 : void DTCLib::DTC_Registers::ClearRXCDRUnlockCount(DTC_Link_ID const& link)
    5623              : {
    5624            0 :         switch (link)
    5625              :         {
    5626            0 :                 case DTC_Link_0:
    5627            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link0);
    5628            0 :                         break;
    5629            0 :                 case DTC_Link_1:
    5630            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link1);
    5631            0 :                         break;
    5632            0 :                 case DTC_Link_2:
    5633            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link2);
    5634            0 :                         break;
    5635            0 :                 case DTC_Link_3:
    5636            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link3);
    5637            0 :                         break;
    5638            0 :                 case DTC_Link_4:
    5639            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link4);
    5640            0 :                         break;
    5641            0 :                 case DTC_Link_5:
    5642            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link5);
    5643            0 :                         break;
    5644            0 :                 case DTC_Link_CFO:
    5645            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_CFOLink);
    5646            0 :                         break;
    5647            0 :                 default: {
    5648            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5649            0 :                         __SS_THROW__;
    5650            0 :                 }
    5651              :         }
    5652            0 : }
    5653              : 
    5654            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink0()
    5655              : {
    5656            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link0);
    5657            0 :         form.description = "RX CDR Unlock Count Link 0";
    5658            0 :         std::stringstream o;
    5659            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_0, form.value);
    5660            0 :         form.vals.push_back(o.str());
    5661            0 :         return form;
    5662            0 : }
    5663              : 
    5664            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink1()
    5665              : {
    5666            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link1);
    5667            0 :         form.description = "RX CDR Unlock Count Link 1";
    5668            0 :         std::stringstream o;
    5669            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_1, form.value);
    5670            0 :         form.vals.push_back(o.str());
    5671            0 :         return form;
    5672            0 : }
    5673              : 
    5674            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink2()
    5675              : {
    5676            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link2);
    5677            0 :         form.description = "RX CDR Unlock Count Link 2";
    5678            0 :         std::stringstream o;
    5679            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_2, form.value);
    5680            0 :         form.vals.push_back(o.str());
    5681            0 :         return form;
    5682            0 : }
    5683              : 
    5684            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink3()
    5685              : {
    5686            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link3);
    5687            0 :         form.description = "RX CDR Unlock Count Link 3";
    5688            0 :         std::stringstream o;
    5689            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_3, form.value);
    5690            0 :         form.vals.push_back(o.str());
    5691            0 :         return form;
    5692            0 : }
    5693              : 
    5694            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink4()
    5695              : {
    5696            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link4);
    5697            0 :         form.description = "RX CDR Unlock Count Link 4";
    5698            0 :         std::stringstream o;
    5699            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_4, form.value);
    5700            0 :         form.vals.push_back(o.str());
    5701            0 :         return form;
    5702            0 : }
    5703              : 
    5704            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink5()
    5705              : {
    5706            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link5);
    5707            0 :         form.description = "RX CDR Unlock Count Link 5";
    5708            0 :         std::stringstream o;
    5709            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_5, form.value);
    5710            0 :         form.vals.push_back(o.str());
    5711            0 :         return form;
    5712            0 : }
    5713              : 
    5714            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountCFOLink()
    5715              : {
    5716            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_CFOLink);
    5717            0 :         form.description = "RX CDR Unlock Count CFO Link";
    5718            0 :         std::stringstream o;
    5719            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_CFO, form.value);
    5720            0 :         form.vals.push_back(o.str());
    5721            0 :         return form;
    5722            0 : }
    5723              : 
    5724            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorUnlockCount(std::optional<uint32_t> val)
    5725              : {
    5726            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuatorLossOfLockCount);
    5727              : }
    5728              : 
    5729            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorUnlockCount()
    5730              : {
    5731            0 :         WriteRegister_(1, DTC_Register_JitterAttenuatorLossOfLockCount);
    5732            0 : }
    5733              : 
    5734            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorUnlockCount()
    5735              : {
    5736            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuatorLossOfLockCount);
    5737            0 :         form.description = "RX Jitter Attenuator Unlock Count";
    5738            0 :         std::stringstream o;
    5739            0 :         o << std::dec << ReadJitterAttenuatorUnlockCount(form.value);
    5740            0 :         form.vals.push_back(o.str());
    5741            0 :         return form;
    5742            0 : }
    5743              : 
    5744            0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLinkEventStartCharacterErrorCount(std::optional<uint32_t> val)
    5745              : {
    5746            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkEventStartErrorCount);
    5747              : }
    5748              : 
    5749            0 : void DTCLib::DTC_Registers::ClearRXCFOLinkEventStartCharacterErrorCount()
    5750              : {
    5751            0 :         WriteRegister_(0, DTC_Register_CFOLinkEventStartErrorCount);
    5752            0 : }
    5753              : 
    5754            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLinkEventStartCharacterErrorCount()
    5755              : {
    5756            0 :         auto form = CreateFormatter(DTC_Register_CFOLinkEventStartErrorCount);
    5757            0 :         form.description = "CFO Link Event Start Error Count";
    5758            0 :         std::stringstream o;
    5759            0 :         o << std::dec << ReadRXCFOLinkEventStartCharacterErrorCount(form.value);
    5760            0 :         form.vals.push_back(o.str());
    5761            0 :         return form;
    5762            0 : }
    5763              : 
    5764            0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLink40MHzCharacterErrorCount(std::optional<uint32_t> val)
    5765              : {
    5766            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLink40MHzErrorCount);
    5767              : }
    5768              : 
    5769            0 : void DTCLib::DTC_Registers::ClearRXCFOLink40MHzCharacterErrorCount()
    5770              : {
    5771            0 :         WriteRegister_(0, DTC_Register_CFOLink40MHzErrorCount);
    5772            0 : }
    5773              : 
    5774            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLink40MHzCharacterErrorCount()
    5775              : {
    5776            0 :         auto form = CreateFormatter(DTC_Register_CFOLink40MHzErrorCount);
    5777            0 :         form.description = "CFO Link 40 MHz Error Count";
    5778            0 :         std::stringstream o;
    5779            0 :         o << std::dec << ReadRXCFOLink40MHzCharacterErrorCount(form.value);
    5780            0 :         form.vals.push_back(o.str());
    5781            0 :         return form;
    5782            0 : }
    5783              : 
    5784            0 : uint32_t DTCLib::DTC_Registers::ReadInputBufferFragmentDumpCount(std::optional<uint32_t> val)
    5785              : {
    5786            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferDropCount);
    5787              : }
    5788              : 
    5789            0 : void DTCLib::DTC_Registers::ClearInputBufferFragmentDumpCount()
    5790              : {
    5791            0 :         WriteRegister_(0, DTC_Register_InputBufferDropCount);
    5792            0 : }
    5793              : 
    5794            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatInputBufferFragmentDumpCount()
    5795              : {
    5796            0 :         auto form = CreateFormatter(DTC_Register_InputBufferDropCount);
    5797            0 :         form.description = "Input Buffer Fragment Drop Count";
    5798            0 :         std::stringstream o;
    5799            0 :         o << std::dec << ReadInputBufferFragmentDumpCount(form.value);
    5800            0 :         form.vals.push_back(o.str());
    5801            0 :         return form;
    5802            0 : }
    5803              : 
    5804            0 : uint32_t DTCLib::DTC_Registers::ReadOutputBufferFragmentDumpCount(std::optional<uint32_t> val)
    5805              : {
    5806            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferDropCount);
    5807              : }
    5808              : 
    5809            0 : void DTCLib::DTC_Registers::ClearOutputBufferFragmentDumpCount()
    5810              : {
    5811            0 :         WriteRegister_(0, DTC_Register_OutputBufferDropCount);
    5812            0 : }
    5813              : 
    5814            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatOutputBufferFragmentDumpCount()
    5815              : {
    5816            0 :         auto form = CreateFormatter(DTC_Register_OutputBufferDropCount);
    5817            0 :         form.description = "Output Buffer Fragment Drop Count";
    5818            0 :         std::stringstream o;
    5819            0 :         o << std::dec << ReadOutputBufferFragmentDumpCount(form.value);
    5820            0 :         form.vals.push_back(o.str());
    5821            0 :         return form;
    5822            0 : }
    5823              : 
    5824            0 : uint32_t DTCLib::DTC_Registers::ReadRTFHistIdelay(std::optional<uint32_t> val)
    5825              : {
    5826            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_RTFHistIdelay);
    5827              : }
    5828              : 
    5829            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRTFHistIdelay()
    5830              : {
    5831            0 :         auto form = CreateFormatter(DTC_Register_RTFHistIdelay);
    5832            0 :         form.description = "RTF Histogram & IDELAY Status";
    5833            0 :         form.vals.push_back("([ x = 1 (hi) ])");
    5834              : 
    5835            0 :         uint32_t idelay_tap = (form.value >> 27) & 0x1F;
    5836            0 :         form.vals.push_back(std::string("IDELAY Tap Count Value:      [") +
    5837            0 :                                                 std::to_string(idelay_tap) + "]");
    5838              : 
    5839            0 :         form.vals.push_back(std::string("IDELAY Ready:                [") +
    5840            0 :                                                 (((form.value >> 26) & 1) ? "x" : " ") + "]");
    5841              : 
    5842            0 :         form.vals.push_back("");
    5843              : 
    5844            0 :         form.vals.push_back("RTF Histogram Bins (3-bit counts, 0-7):");
    5845            0 :         for (int bin = 0; bin < 5; ++bin)
    5846              :         {
    5847            0 :                 int shift = 11 + bin * 3;
    5848            0 :                 uint32_t count = (form.value >> shift) & 0x7;
    5849            0 :                 form.vals.push_back(std::string("  Bin ") + std::to_string(bin) +
    5850            0 :                                                         ": [" + std::to_string(count) + "]");
    5851              :         }
    5852              : 
    5853            0 :         form.vals.push_back("");
    5854              : 
    5855            0 :         form.vals.push_back(std::string("Histogram Saturated:         [") +
    5856            0 :                                                 (((form.value >> 10) & 1) ? "x" : " ") + "]");
    5857              : 
    5858            0 :         uint32_t sat_bin = (form.value >> 7) & 0x7;
    5859            0 :         form.vals.push_back(std::string("Saturated Bin:               [") +
    5860            0 :                                                 std::to_string(sat_bin) + "]");
    5861              : 
    5862            0 :         std::stringstream rs;
    5863            0 :         rs << "0x" << std::hex << (form.value & 0x7F);
    5864            0 :         form.vals.push_back(std::string("Reserved [6:0]:              [") + rs.str() + "]");
    5865              : 
    5866            0 :         return form;
    5867            0 : }
    5868              : 
    5869            0 : void DTCLib::DTC_Registers::SetSoftwareDataRequest(const DTC_EventWindowTag& ts)
    5870              : {
    5871            0 :         auto timestamp = ts.GetEventWindowTag();
    5872            0 :         auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
    5873            0 :         timestamp >>= 32;
    5874            0 :         auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
    5875              : 
    5876            0 :         WriteRegister_(timestampHigh, DTC_Register_DataRequest_High);
    5877            0 :         WriteRegister_(timestampLow, DTC_Register_DataRequest_Low);  // this triggers the DR
    5878            0 : }
    5879              : 
    5880            0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadSoftwareDataRequest(std::optional<uint32_t> val)
    5881              : {
    5882            0 :         auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_DataRequest_Low);
    5883            0 :         DTC_EventWindowTag output;
    5884            0 :         output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_DataRequest_High)));
    5885            0 :         return output;
    5886            0 : }
    5887              : 
    5888            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestLow()
    5889              : {
    5890            0 :         auto form = CreateFormatter(DTC_Register_DataRequest_Low);
    5891            0 :         form.description = "Software Data Request Low";
    5892            0 :         std::stringstream o;
    5893            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_Low);
    5894            0 :         form.vals.push_back(o.str());
    5895            0 :         return form;
    5896            0 : }
    5897              : 
    5898            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestHigh()
    5899              : {
    5900            0 :         auto form = CreateFormatter(DTC_Register_DataRequest_High);
    5901            0 :         form.description = "Software Data Request High";
    5902            0 :         std::stringstream o;
    5903            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_High);
    5904            0 :         form.vals.push_back(o.str());
    5905            0 :         return form;
    5906            0 : }
    5907              : 
    5908              : // FPGA PROM Program Status Register
    5909              : /// <summary>
    5910              : /// Read the full bit on the FPGA PROM FIFO
    5911              : /// </summary>
    5912              : /// <returns>the full bit on the FPGA PROM FIFO</returns>
    5913            0 : bool DTCLib::DTC_Registers::ReadFPGAPROMProgramFIFOFull(std::optional<uint32_t> val)
    5914              : {
    5915            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
    5916            0 :         return dataSet[1];
    5917              : }
    5918              : 
    5919              : /// <summary>
    5920              : /// Read whether the FPGA PROM is ready for data
    5921              : /// </summary>
    5922              : /// <returns>whether the FPGA PROM is ready for data</returns>
    5923            0 : bool DTCLib::DTC_Registers::ReadFPGAPROMReady(std::optional<uint32_t> val)
    5924              : {
    5925            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
    5926            0 :         return dataSet[0];
    5927              : }
    5928              : 
    5929              : /// <summary>
    5930              : /// Formats the register's current value for register dumps
    5931              : /// </summary>
    5932              : /// <returns>RegisterFormatter object containing register information</returns>
    5933            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGAPROMProgramStatus()
    5934              : {
    5935            0 :         auto form = CreateFormatter(DTC_Register_FPGAPROMProgramStatus);
    5936            0 :         form.description = "FPGA PROM Program Status";
    5937            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5938            0 :         form.vals.push_back(std::string("FPGA PROM Program FIFO Full: [") + (ReadFPGAPROMProgramFIFOFull(form.value) ? "x" : " ") +
    5939              :                                                 "]");
    5940            0 :         form.vals.push_back(std::string("FPGA PROM Ready:             [") + (ReadFPGAPROMReady(form.value) ? "x" : " ") + "]");
    5941            0 :         return form;
    5942            0 : }
    5943              : 
    5944              : // FPGA Core Access Register
    5945              : /// <summary>
    5946              : /// Performs the chants necessary to reload the DTC firmware
    5947              : /// </summary>
    5948            0 : void DTCLib::DTC_Registers::ReloadFPGAFirmware()
    5949              : {
    5950            0 :         WriteRegister_(0xFFFFFFFF, DTC_Register_FPGACoreAccess);
    5951            0 :         while (ReadFPGACoreAccessFIFOFull())
    5952              :         {
    5953            0 :                 usleep(10);
    5954              :         }
    5955            0 :         WriteRegister_(0xAA995566, DTC_Register_FPGACoreAccess);
    5956            0 :         while (ReadFPGACoreAccessFIFOFull())
    5957              :         {
    5958            0 :                 usleep(10);
    5959              :         }
    5960            0 :         WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
    5961            0 :         while (ReadFPGACoreAccessFIFOFull())
    5962              :         {
    5963            0 :                 usleep(10);
    5964              :         }
    5965            0 :         WriteRegister_(0x30020001, DTC_Register_FPGACoreAccess);
    5966            0 :         while (ReadFPGACoreAccessFIFOFull())
    5967              :         {
    5968            0 :                 usleep(10);
    5969              :         }
    5970            0 :         WriteRegister_(0x00000000, DTC_Register_FPGACoreAccess);
    5971            0 :         while (ReadFPGACoreAccessFIFOFull())
    5972              :         {
    5973            0 :                 usleep(10);
    5974              :         }
    5975            0 :         WriteRegister_(0x30008001, DTC_Register_FPGACoreAccess);
    5976            0 :         while (ReadFPGACoreAccessFIFOFull())
    5977              :         {
    5978            0 :                 usleep(10);
    5979              :         }
    5980            0 :         WriteRegister_(0x0000000F, DTC_Register_FPGACoreAccess);
    5981            0 :         while (ReadFPGACoreAccessFIFOFull())
    5982              :         {
    5983            0 :                 usleep(10);
    5984              :         }
    5985            0 :         WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
    5986            0 : }
    5987              : 
    5988              : /// <summary>
    5989              : /// Read the FPGA Core Access FIFO Full bit
    5990              : /// </summary>
    5991              : /// <returns>Whether the FPGA Core Access FIFO is full</returns>
    5992            0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOFull(std::optional<uint32_t> val)
    5993              : {
    5994            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
    5995            0 :         return dataSet[1];
    5996              : }
    5997              : 
    5998              : /// <summary>
    5999              : /// Read the FPGA Core Access FIFO Empty bit
    6000              : /// </summary>
    6001              : /// <returns>Whether the FPGA Core Access FIFO is empty</returns>
    6002            0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOEmpty(std::optional<uint32_t> val)
    6003              : {
    6004            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
    6005            0 :         return dataSet[0];
    6006              : }
    6007              : 
    6008              : /// <summary>
    6009              : /// Formats the register's current value for register dumps
    6010              : /// </summary>
    6011              : /// <returns>RegisterFormatter object containing register information</returns>
    6012            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGACoreAccess()
    6013              : {
    6014            0 :         auto form = CreateFormatter(DTC_Register_FPGACoreAccess);
    6015            0 :         form.description = "FPGA Core Access";
    6016            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6017            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Full:  [") + (ReadFPGACoreAccessFIFOFull(form.value) ? "x" : " ") + "]");
    6018            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Empty: [") + (ReadFPGACoreAccessFIFOEmpty(form.value) ? "x" : " ") +
    6019              :                                                 "]");
    6020              : 
    6021            0 :         return form;
    6022            0 : }
    6023              : 
    6024            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
    6025              : {
    6026            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6027            0 :         return data[9];
    6028              : }
    6029              : 
    6030            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
    6031              : {
    6032            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6033            0 :         return data[8];
    6034              : }
    6035              : 
    6036            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
    6037              : {
    6038            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6039            0 :         return data[7];
    6040              : }
    6041              : 
    6042            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
    6043              : {
    6044            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6045            0 :         return data[6];
    6046              : }
    6047              : 
    6048            0 : bool DTCLib::DTC_Registers::ReadLatchedSpareSMAInputOKError(std::optional<uint32_t> val)
    6049              : {
    6050            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6051            0 :         return data[5];
    6052              : }
    6053              : 
    6054            0 : void DTCLib::DTC_Registers::ClearLatchedSpareSMAInputOKError()
    6055              : {
    6056            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6057            0 :         data[5] = 1;
    6058            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6059            0 : }
    6060              : 
    6061            0 : bool DTCLib::DTC_Registers::ReadLatchedEventMarkerSMAInputOKError(std::optional<uint32_t> val)
    6062              : {
    6063            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6064            0 :         return data[4];
    6065              : }
    6066              : 
    6067            0 : void DTCLib::DTC_Registers::ClearLatchedEventMarkerSMASMAInputOKError()
    6068              : {
    6069            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6070            0 :         data[4] = 1;
    6071            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6072            0 : }
    6073              : 
    6074            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
    6075              : {
    6076            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6077            0 :         return data[3];
    6078              : }
    6079              : 
    6080            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink3()
    6081              : {
    6082            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6083            0 :         data[3] = 1;
    6084            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6085            0 : }
    6086              : 
    6087            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
    6088              : {
    6089            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6090            0 :         return data[2];
    6091              : }
    6092              : 
    6093            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink2()
    6094              : {
    6095            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6096            0 :         data[2] = 1;
    6097            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6098            0 : }
    6099              : 
    6100            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
    6101              : {
    6102            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6103            0 :         return data[1];
    6104              : }
    6105              : 
    6106            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink1()
    6107              : {
    6108            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6109            0 :         data[1] = 1;
    6110            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6111            0 : }
    6112              : 
    6113            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
    6114              : {
    6115            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6116            0 :         return data[0];
    6117              : }
    6118              : 
    6119            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink0()
    6120              : {
    6121            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6122            0 :         data[0] = 1;
    6123            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6124            0 : }
    6125              : 
    6126            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSlowOpticalLinkControlStatus()
    6127              : {
    6128            0 :         auto form = CreateFormatter(DTC_Register_SFPControlStatus);
    6129            0 :         form.description = "Slow Optical Link Control Status";
    6130            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6131            0 :         form.vals.push_back(std::string("RX OK SOL Link 3:           [") + (ReadRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
    6132            0 :         form.vals.push_back(std::string("RX OK SOL Link 2:           [") + (ReadRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
    6133            0 :         form.vals.push_back(std::string("RX OK SOL Link 1:           [") + (ReadRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
    6134            0 :         form.vals.push_back(std::string("RX OK SOL Link 0:           [") + (ReadRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
    6135            0 :         form.vals.push_back(std::string("Latched Spare SMA Input:    [") + (ReadLatchedSpareSMAInputOKError(form.value) ? "x" : " ") + "]");
    6136            0 :         form.vals.push_back(std::string("Latched Event Marker Input: [") + (ReadLatchedEventMarkerSMAInputOKError(form.value) ? "x" : " ") + "]");
    6137            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 3:   [") + (ReadLatchedRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
    6138            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 2:   [") + (ReadLatchedRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
    6139            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 1:   [") + (ReadLatchedRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
    6140            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 0:   [") + (ReadLatchedRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
    6141            0 :         return form;
    6142            0 : }
    6143              : 
    6144            0 : bool DTCLib::DTC_Registers::ReadSERDESInduceErrorEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6145              : {
    6146            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
    6147            0 :         return data[link];
    6148              : }
    6149              : 
    6150            0 : void DTCLib::DTC_Registers::EnableSERDESInduceError(DTC_Link_ID const& link)
    6151              : {
    6152            0 :         SetBit_(DTC_Register_DiagSERDESErrorEnable, link, true);
    6153            0 : }
    6154              : 
    6155            0 : void DTCLib::DTC_Registers::DisableSERDESInduceError(DTC_Link_ID const& link)
    6156              : {
    6157            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
    6158            0 :         data[link] = 0;
    6159            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DiagSERDESErrorEnable);
    6160            0 : }
    6161              : 
    6162            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorEnable()
    6163              : {
    6164            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    6165            0 :         form.description = "SERDES Induce Error Enable";
    6166            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6167            0 :         for (auto r : DTC_ROC_Links)
    6168            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    6169            0 :                                                         (ReadSERDESInduceErrorEnable(r, form.value) ? "x" : " ") + "]");
    6170              : 
    6171            0 :         return form;
    6172            0 : }
    6173              : 
    6174            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6175              : {
    6176            0 :         switch (link)
    6177              :         {
    6178            0 :                 case DTC_Link_0:
    6179            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket0);
    6180            0 :                 case DTC_Link_1:
    6181            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket1);
    6182            0 :                 case DTC_Link_2:
    6183            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket2);
    6184            0 :                 case DTC_Link_3:
    6185            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket3);
    6186            0 :                 case DTC_Link_4:
    6187            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket4);
    6188            0 :                 case DTC_Link_5:
    6189            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket5);
    6190            0 :                 default: {
    6191            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6192            0 :                         __SS_THROW__;
    6193            0 :                 }
    6194              :         }
    6195              : }
    6196              : 
    6197            0 : void DTCLib::DTC_Registers::SetSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, uint32_t sequence)
    6198              : {
    6199            0 :         switch (link)
    6200              :         {
    6201            0 :                 case DTC_Link_0:
    6202            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket0);
    6203            0 :                         break;
    6204            0 :                 case DTC_Link_1:
    6205            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket1);
    6206            0 :                         break;
    6207            0 :                 case DTC_Link_2:
    6208            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket2);
    6209            0 :                         break;
    6210            0 :                 case DTC_Link_3:
    6211            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket3);
    6212            0 :                         break;
    6213            0 :                 case DTC_Link_4:
    6214            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket4);
    6215            0 :                         break;
    6216            0 :                 case DTC_Link_5:
    6217            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket5);
    6218            0 :                         break;
    6219            0 :                 default: {
    6220            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6221            0 :                         __SS_THROW__;
    6222            0 :                 }
    6223              :         }
    6224            0 : }
    6225              : 
    6226            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink0()
    6227              : {
    6228            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket0);
    6229            0 :         form.description = "Link 0 Induced Error Sequence Number";
    6230            0 :         std::stringstream o;
    6231            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_0, form.value);
    6232            0 :         form.vals.push_back(o.str());
    6233            0 :         return form;
    6234            0 : }
    6235              : 
    6236            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink1()
    6237              : {
    6238            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket1);
    6239            0 :         form.description = "Link 1 Induced Error Sequence Number";
    6240            0 :         std::stringstream o;
    6241            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_1, form.value);
    6242            0 :         form.vals.push_back(o.str());
    6243            0 :         return form;
    6244            0 : }
    6245              : 
    6246            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink2()
    6247              : {
    6248            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket2);
    6249            0 :         form.description = "Link 2 Induced Error Sequence Number";
    6250            0 :         std::stringstream o;
    6251            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_2, form.value);
    6252            0 :         form.vals.push_back(o.str());
    6253            0 :         return form;
    6254            0 : }
    6255              : 
    6256            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink3()
    6257              : {
    6258            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket3);
    6259            0 :         form.description = "Link 3 Induced Error Sequence Number";
    6260            0 :         std::stringstream o;
    6261            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_3, form.value);
    6262            0 :         form.vals.push_back(o.str());
    6263            0 :         return form;
    6264            0 : }
    6265              : 
    6266            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink4()
    6267              : {
    6268            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket4);
    6269            0 :         form.description = "Link 4 Induced Error Sequence Number";
    6270            0 :         std::stringstream o;
    6271            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_4, form.value);
    6272            0 :         form.vals.push_back(o.str());
    6273            0 :         return form;
    6274            0 : }
    6275              : 
    6276            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink5()
    6277              : {
    6278            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket5);
    6279            0 :         form.description = "Link 5 Induced Error Sequence Number";
    6280            0 :         std::stringstream o;
    6281            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_5, form.value);
    6282            0 :         form.vals.push_back(o.str());
    6283            0 :         return form;
    6284            0 : }
    6285              : 
    6286              : // DTCLib::DTC_DDRFlags DTCLib::DTC_Registers::ReadDDRFlags(uint8_t buffer_id)
    6287              : // {
    6288              : //      return DTC_DDRFlags(ReadDDRLinkBufferFullFlags()[buffer_id],
    6289              : //                                              ReadDDRLinkBufferEmptyFlags()[buffer_id],
    6290              : //                                              ReadDDRLinkBufferHalfFullFlags()[buffer_id],
    6291              : //                                              ReadDDREventBuilderBufferFullFlags()[buffer_id],
    6292              : //                                              ReadDDREventBuilderBufferEmptyFlags()[buffer_id],
    6293              : //                                              ReadDDREventBuilderBufferHalfFullFlags()[buffer_id]);
    6294              : // }
    6295              : 
    6296              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferFullFlags()
    6297              : // {
    6298              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags0);
    6299              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags1);
    6300              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags2);
    6301              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags3);
    6302              : //      std::bitset<128> out;
    6303              : //      for (size_t ii = 0; ii < 32; ++ii)
    6304              : //      {
    6305              : //              out[ii] = (word0 >> ii) & 0x1;
    6306              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6307              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6308              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6309              : //      }
    6310              : //      return out;
    6311              : // }
    6312              : 
    6313              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferEmptyFlags()
    6314              : // {
    6315              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6316              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6317              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6318              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6319              : //      std::bitset<128> out;
    6320              : //      for (size_t ii = 0; ii < 32; ++ii)
    6321              : //      {
    6322              : //              out[ii] = (word0 >> ii) & 0x1;
    6323              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6324              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6325              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6326              : //      }
    6327              : //      return out;
    6328              : // }
    6329              : 
    6330              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferHalfFullFlags()
    6331              : // {
    6332              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6333              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6334              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6335              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6336              : //      std::bitset<128> out;
    6337              : //      for (size_t ii = 0; ii < 32; ++ii)
    6338              : //      {
    6339              : //              out[ii] = (word0 >> ii) & 0x1;
    6340              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6341              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6342              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6343              : //      }
    6344              : //      return out;
    6345              : // }
    6346              : 
    6347              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferFullFlags()
    6348              : // {
    6349              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags0);
    6350              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags1);
    6351              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags2);
    6352              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags3);
    6353              : //      std::bitset<128> out;
    6354              : //      for (size_t ii = 0; ii < 32; ++ii)
    6355              : //      {
    6356              : //              out[ii] = (word0 >> ii) & 0x1;
    6357              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6358              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6359              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6360              : //      }
    6361              : //      return out;
    6362              : // }
    6363              : 
    6364              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferEmptyFlags()
    6365              : // {
    6366              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags0);
    6367              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags1);
    6368              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags2);
    6369              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags3);
    6370              : //      std::bitset<128> out;
    6371              : //      for (size_t ii = 0; ii < 32; ++ii)
    6372              : //      {
    6373              : //              out[ii] = (word0 >> ii) & 0x1;
    6374              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6375              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6376              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6377              : //      }
    6378              : //      return out;
    6379              : // }
    6380              : 
    6381              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferHalfFullFlags()
    6382              : // {
    6383              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags0);
    6384              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags1);
    6385              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags2);
    6386              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags3);
    6387              : //      std::bitset<128> out;
    6388              : //      for (size_t ii = 0; ii < 32; ++ii)
    6389              : //      {
    6390              : //              out[ii] = (word0 >> ii) & 0x1;
    6391              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6392              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6393              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6394              : //      }
    6395              : //      return out;
    6396              : // }
    6397              : 
    6398              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags0()
    6399              : // {
    6400              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6401              : //      form.description = "DDR Link Buffer Empty Flags 0-31";
    6402              : //      return form;
    6403              : // }
    6404              : 
    6405              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags1()
    6406              : // {
    6407              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6408              : //      form.description = "DDR Link Buffer Empty Flags 63-32";
    6409              : //      return form;
    6410              : // }
    6411              : 
    6412              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags2()
    6413              : // {
    6414              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6415              : //      form.description = "DDR Link Buffer Empty Flags 95-64";
    6416              : //      return form;
    6417              : // }
    6418              : 
    6419              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags3()
    6420              : // {
    6421              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6422              : //      form.description = "DDR Link Buffer Empty Flags 127-96";
    6423              : //      return form;
    6424              : // }
    6425              : 
    6426              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags0()
    6427              : // {
    6428              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6429              : //      form.description = "DDR Link Buffer Half-Full Flags 0-31";
    6430              : //      return form;
    6431              : // }
    6432              : 
    6433              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags1()
    6434              : // {
    6435              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6436              : //      form.description = "DDR Link Buffer Half-Full Flags 63-32";
    6437              : //      return form;
    6438              : // }
    6439              : 
    6440              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags2()
    6441              : // {
    6442              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6443              : //      form.description = "DDR Link Buffer Half-Full Flags 95-64";
    6444              : //      return form;
    6445              : // }
    6446              : 
    6447              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags3()
    6448              : // {
    6449              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6450              : //      form.description = "DDR Link Buffer Half-Full Flags 127-96";
    6451              : //      return form;
    6452              : // }
    6453              : 
    6454              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags0()
    6455              : // {
    6456              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6457              : //      form.description = "DDR Link Buffer Full Flags 0-31";
    6458              : //      return form;
    6459              : // }
    6460              : 
    6461              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags1()
    6462              : // {
    6463              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6464              : //      form.description = "DDR Link Buffer Full Flags 63-32";
    6465              : //      return form;
    6466              : // }
    6467              : 
    6468              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags2()
    6469              : // {
    6470              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6471              : //      form.description = "DDR Link Buffer Full Flags 95-64";
    6472              : //      return form;
    6473              : // }
    6474              : 
    6475              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags3()
    6476              : // {
    6477              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6478              : //      form.description = "DDR Link Buffer Full Flags 127-96";
    6479              : //      return form;
    6480              : // }
    6481              : 
    6482              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags0()
    6483              : // {
    6484              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags0);
    6485              : //      form.description = "DDR EVB Buffer Empty Flags 0-31";
    6486              : //      return form;
    6487              : // }
    6488              : 
    6489              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags1()
    6490              : // {
    6491              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags1);
    6492              : //      form.description = "DDR EVB Buffer Empty Flags 63-32";
    6493              : //      return form;
    6494              : // }
    6495              : 
    6496              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags2()
    6497              : // {
    6498              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags2);
    6499              : //      form.description = "DDR EVB Buffer Empty Flags 95-64";
    6500              : //      return form;
    6501              : // }
    6502              : 
    6503              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags3()
    6504              : // {
    6505              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags3);
    6506              : //      form.description = "DDR EVB Buffer Empty Flags 127-96";
    6507              : //      return form;
    6508              : // }
    6509              : 
    6510              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags0()
    6511              : // {
    6512              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6513              : //      form.description = "DDR Link Buffer Half-Full Flags 0-31";
    6514              : //      return form;
    6515              : // }
    6516              : 
    6517              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags1()
    6518              : // {
    6519              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6520              : //      form.description = "DDR Link Buffer Half-Full Flags 63-32";
    6521              : //      return form;
    6522              : // }
    6523              : 
    6524              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags2()
    6525              : // {
    6526              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6527              : //      form.description = "DDR Link Buffer Half-Full Flags 95-64";
    6528              : //      return form;
    6529              : // }
    6530              : 
    6531              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags3()
    6532              : // {
    6533              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6534              : //      form.description = "DDR Link Buffer Half-Full Flags 127-96";
    6535              : //      return form;
    6536              : // }
    6537              : 
    6538              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags0()
    6539              : // {
    6540              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags0);
    6541              : //      form.description = "DDR Link Buffer Full Flags 0-31";
    6542              : //      return form;
    6543              : // }
    6544              : 
    6545              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags1()
    6546              : // {
    6547              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags1);
    6548              : //      form.description = "DDR Link Buffer Full Flags 63-32";
    6549              : //      return form;
    6550              : // }
    6551              : 
    6552              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags2()
    6553              : // {
    6554              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags2);
    6555              : //      form.description = "DDR Link Buffer Full Flags 95-64";
    6556              : //      return form;
    6557              : // }
    6558              : 
    6559              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags3()
    6560              : // {
    6561              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags3);
    6562              : //      form.description = "DDR Link Buffer Full Flags 127-96";
    6563              : //      return form;
    6564              : // }
    6565              : 
    6566            0 : uint32_t DTCLib::DTC_Registers::ReadDataPendingDiagnosticTimer(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6567              : {
    6568            0 :         switch (link)
    6569              :         {
    6570            0 :                 case DTC_Link_0:
    6571            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link0);
    6572            0 :                 case DTC_Link_1:
    6573            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link1);
    6574            0 :                 case DTC_Link_2:
    6575            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link2);
    6576            0 :                 case DTC_Link_3:
    6577            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link3);
    6578            0 :                 case DTC_Link_4:
    6579            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link4);
    6580            0 :                 case DTC_Link_5:
    6581            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link5);
    6582            0 :                 default: {
    6583            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6584            0 :                         __SS_THROW__;
    6585            0 :                 }
    6586              :         }
    6587              : }
    6588              : 
    6589            0 : void DTCLib::DTC_Registers::ResetDataPendingDiagnosticTimerFIFO(DTC_Link_ID const& link)
    6590              : {
    6591            0 :         switch (link)
    6592              :         {
    6593            0 :                 case DTC_Link_0:
    6594            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link0);
    6595            0 :                         break;
    6596            0 :                 case DTC_Link_1:
    6597            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link1);
    6598            0 :                         break;
    6599            0 :                 case DTC_Link_2:
    6600            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link2);
    6601            0 :                         break;
    6602            0 :                 case DTC_Link_3:
    6603            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link3);
    6604            0 :                         break;
    6605            0 :                 case DTC_Link_4:
    6606            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link4);
    6607            0 :                         break;
    6608            0 :                 case DTC_Link_5:
    6609            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link5);
    6610            0 :                         break;
    6611            0 :                 default: {
    6612            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6613            0 :                         __SS_THROW__;
    6614            0 :                 }
    6615              :         }
    6616            0 : }
    6617              : 
    6618            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink0()
    6619              : {
    6620            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link0);
    6621            0 :         form.description = "Data Pending Diagnostic Timer Link 0";
    6622            0 :         std::stringstream o;
    6623            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_0, form.value);
    6624            0 :         form.vals.push_back(o.str());
    6625            0 :         return form;
    6626            0 : }
    6627              : 
    6628            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink1()
    6629              : {
    6630            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link1);
    6631            0 :         form.description = "Data Pending Diagnostic Timer Link 1";
    6632            0 :         std::stringstream o;
    6633            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_1, form.value);
    6634            0 :         form.vals.push_back(o.str());
    6635            0 :         return form;
    6636            0 : }
    6637              : 
    6638            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink2()
    6639              : {
    6640            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link2);
    6641            0 :         form.description = "Data Pending Diagnostic Timer Link 2";
    6642            0 :         std::stringstream o;
    6643            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_2, form.value);
    6644            0 :         form.vals.push_back(o.str());
    6645            0 :         return form;
    6646            0 : }
    6647              : 
    6648            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink3()
    6649              : {
    6650            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link3);
    6651            0 :         form.description = "Data Pending Diagnostic Timer Link 3";
    6652            0 :         std::stringstream o;
    6653            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_3, form.value);
    6654            0 :         form.vals.push_back(o.str());
    6655            0 :         return form;
    6656            0 : }
    6657              : 
    6658            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink4()
    6659              : {
    6660            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link4);
    6661            0 :         form.description = "Data Pending Diagnostic Timer Link 4";
    6662            0 :         std::stringstream o;
    6663            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_4, form.value);
    6664            0 :         form.vals.push_back(o.str());
    6665            0 :         return form;
    6666            0 : }
    6667              : 
    6668            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink5()
    6669              : {
    6670            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link5);
    6671            0 :         form.description = "Data Pending Diagnostic Timer Link 5";
    6672            0 :         std::stringstream o;
    6673            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_5, form.value);
    6674            0 :         form.vals.push_back(o.str());
    6675            0 :         return form;
    6676            0 : }
    6677              : 
    6678            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6679              : {
    6680              :         DTC_Register reg;
    6681            0 :         switch (link)
    6682              :         {
    6683            0 :                 case DTC_Link_0:
    6684            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
    6685            0 :                         break;
    6686            0 :                 case DTC_Link_1:
    6687            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
    6688            0 :                         break;
    6689            0 :                 case DTC_Link_2:
    6690            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
    6691            0 :                         break;
    6692            0 :                 case DTC_Link_3:
    6693            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
    6694            0 :                         break;
    6695            0 :                 case DTC_Link_4:
    6696            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
    6697            0 :                         break;
    6698            0 :                 case DTC_Link_5:
    6699            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
    6700            0 :                         break;
    6701            0 :                 case DTC_Link_CFO:
    6702            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
    6703            0 :                         break;
    6704            0 :                 default: {
    6705            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6706            0 :                         __SS_THROW__;
    6707            0 :                 }
    6708              :         }
    6709            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    6710              : }
    6711            0 : void DTCLib::DTC_Registers::ClearSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link)
    6712              : {
    6713              :         DTC_Register reg;
    6714            0 :         switch (link)
    6715              :         {
    6716            0 :                 case DTC_Link_0:
    6717            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
    6718            0 :                         break;
    6719            0 :                 case DTC_Link_1:
    6720            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
    6721            0 :                         break;
    6722            0 :                 case DTC_Link_2:
    6723            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
    6724            0 :                         break;
    6725            0 :                 case DTC_Link_3:
    6726            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
    6727            0 :                         break;
    6728            0 :                 case DTC_Link_4:
    6729            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
    6730            0 :                         break;
    6731            0 :                 case DTC_Link_5:
    6732            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
    6733            0 :                         break;
    6734            0 :                 case DTC_Link_CFO:
    6735            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
    6736            0 :                         break;
    6737            0 :                 default: {
    6738            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6739            0 :                         __SS_THROW__;
    6740            0 :                 }
    6741              :         }
    6742            0 :         WriteRegister_(1, reg);
    6743            0 : }
    6744              : 
    6745            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink0()
    6746              : {
    6747            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0);
    6748            0 :         form.description = "SERDES Character Not In Table Error Count Link 0";
    6749            0 :         std::stringstream o;
    6750            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_0);
    6751            0 :         form.vals.push_back(o.str());
    6752            0 :         return form;
    6753            0 : }
    6754            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink1()
    6755              : {
    6756            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1);
    6757            0 :         form.description = "SERDES Character Not In Table Error Count Link 1";
    6758            0 :         std::stringstream o;
    6759            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_1);
    6760            0 :         form.vals.push_back(o.str());
    6761            0 :         return form;
    6762            0 : }
    6763            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink2()
    6764              : {
    6765            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2);
    6766            0 :         form.description = "SERDES Character Not In Table Error Count Link 2";
    6767            0 :         std::stringstream o;
    6768            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_2);
    6769            0 :         form.vals.push_back(o.str());
    6770            0 :         return form;
    6771            0 : }
    6772            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink3()
    6773              : {
    6774            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3);
    6775            0 :         form.description = "SERDES Character Not In Table Error Count Link 3";
    6776            0 :         std::stringstream o;
    6777            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_3);
    6778            0 :         form.vals.push_back(o.str());
    6779            0 :         return form;
    6780            0 : }
    6781            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink4()
    6782              : {
    6783            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4);
    6784            0 :         form.description = "SERDES Character Not In Table Error Count Link 4";
    6785            0 :         std::stringstream o;
    6786            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_4);
    6787            0 :         form.vals.push_back(o.str());
    6788            0 :         return form;
    6789            0 : }
    6790            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink5()
    6791              : {
    6792            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5);
    6793            0 :         form.description = "SERDES Character Not In Table Error Count Link 5";
    6794            0 :         std::stringstream o;
    6795            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_5);
    6796            0 :         form.vals.push_back(o.str());
    6797            0 :         return form;
    6798            0 : }
    6799            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountCFOLink()
    6800              : {
    6801            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink);
    6802            0 :         form.description = "SERDES Character Not In Table Error Count CFO Link";
    6803            0 :         std::stringstream o;
    6804            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_CFO);
    6805            0 :         form.vals.push_back(o.str());
    6806            0 :         return form;
    6807            0 : }
    6808              : 
    6809            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXDisparityErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6810              : {
    6811              :         DTC_Register reg;
    6812            0 :         switch (link)
    6813              :         {
    6814            0 :                 case DTC_Link_0:
    6815            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
    6816            0 :                         break;
    6817            0 :                 case DTC_Link_1:
    6818            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
    6819            0 :                         break;
    6820            0 :                 case DTC_Link_2:
    6821            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
    6822            0 :                         break;
    6823            0 :                 case DTC_Link_3:
    6824            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
    6825            0 :                         break;
    6826            0 :                 case DTC_Link_4:
    6827            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
    6828            0 :                         break;
    6829            0 :                 case DTC_Link_5:
    6830            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
    6831            0 :                         break;
    6832            0 :                 case DTC_Link_CFO:
    6833            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
    6834            0 :                         break;
    6835            0 :                 default: {
    6836            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6837            0 :                         __SS_THROW__;
    6838            0 :                 }
    6839              :         }
    6840            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    6841              : }
    6842            0 : void DTCLib::DTC_Registers::ClearSERDESRXDisparityErrorCount(DTC_Link_ID const& link)
    6843              : {
    6844              :         DTC_Register reg;
    6845            0 :         switch (link)
    6846              :         {
    6847            0 :                 case DTC_Link_0:
    6848            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
    6849            0 :                         break;
    6850            0 :                 case DTC_Link_1:
    6851            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
    6852            0 :                         break;
    6853            0 :                 case DTC_Link_2:
    6854            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
    6855            0 :                         break;
    6856            0 :                 case DTC_Link_3:
    6857            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
    6858            0 :                         break;
    6859            0 :                 case DTC_Link_4:
    6860            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
    6861            0 :                         break;
    6862            0 :                 case DTC_Link_5:
    6863            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
    6864            0 :                         break;
    6865            0 :                 case DTC_Link_CFO:
    6866            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
    6867            0 :                         break;
    6868            0 :                 default: {
    6869            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6870            0 :                         __SS_THROW__;
    6871            0 :                 }
    6872              :         }
    6873            0 :         WriteRegister_(1, reg);
    6874            0 : }
    6875              : 
    6876            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink0()
    6877              : {
    6878            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link0);
    6879            0 :         form.description = "SERDES RX Disparity Error Count Link 0";
    6880            0 :         std::stringstream o;
    6881            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_0, form.value);
    6882            0 :         form.vals.push_back(o.str());
    6883            0 :         return form;
    6884            0 : }
    6885            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink1()
    6886              : {
    6887            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link1);
    6888            0 :         form.description = "SERDES RX Disparity Error Count Link 1";
    6889            0 :         std::stringstream o;
    6890            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_1, form.value);
    6891            0 :         form.vals.push_back(o.str());
    6892            0 :         return form;
    6893            0 : }
    6894            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink2()
    6895              : {
    6896            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link2);
    6897            0 :         form.description = "SERDES RX Disparity Error Count Link 2";
    6898            0 :         std::stringstream o;
    6899            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_2, form.value);
    6900            0 :         form.vals.push_back(o.str());
    6901            0 :         return form;
    6902            0 : }
    6903            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink3()
    6904              : {
    6905            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link3);
    6906            0 :         form.description = "SERDES RX Disparity Error Count Link 3";
    6907            0 :         std::stringstream o;
    6908            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_3, form.value);
    6909            0 :         form.vals.push_back(o.str());
    6910            0 :         return form;
    6911            0 : }
    6912            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink4()
    6913              : {
    6914            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link4);
    6915            0 :         form.description = "SERDES RX Disparity Error Count Link 4";
    6916            0 :         std::stringstream o;
    6917            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_4, form.value);
    6918            0 :         form.vals.push_back(o.str());
    6919            0 :         return form;
    6920            0 : }
    6921            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink5()
    6922              : {
    6923            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link5);
    6924            0 :         form.description = "SERDES RX Disparity Error Count Link 5";
    6925            0 :         std::stringstream o;
    6926            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_5, form.value);
    6927            0 :         form.vals.push_back(o.str());
    6928            0 :         return form;
    6929            0 : }
    6930            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountCFOLink()
    6931              : {
    6932            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_CFOLink);
    6933            0 :         form.description = "SERDES RX Disparity Error Count CFO Link";
    6934            0 :         std::stringstream o;
    6935            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_CFO, form.value);
    6936            0 :         form.vals.push_back(o.str());
    6937            0 :         return form;
    6938            0 : }
    6939              : 
    6940            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXPRBSErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6941              : {
    6942              :         DTC_Register reg;
    6943            0 :         switch (link)
    6944              :         {
    6945            0 :                 case DTC_Link_0:
    6946            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
    6947            0 :                         break;
    6948            0 :                 case DTC_Link_1:
    6949            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
    6950            0 :                         break;
    6951            0 :                 case DTC_Link_2:
    6952            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
    6953            0 :                         break;
    6954            0 :                 case DTC_Link_3:
    6955            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
    6956            0 :                         break;
    6957            0 :                 case DTC_Link_4:
    6958            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
    6959            0 :                         break;
    6960            0 :                 case DTC_Link_5:
    6961            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
    6962            0 :                         break;
    6963            0 :                 case DTC_Link_CFO:
    6964            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
    6965            0 :                         break;
    6966            0 :                 default: {
    6967            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6968            0 :                         __SS_THROW__;
    6969            0 :                 }
    6970              :         }
    6971            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    6972              : }
    6973            0 : void DTCLib::DTC_Registers::ClearSERDESRXPRBSErrorCount(DTC_Link_ID const& link)
    6974              : {
    6975              :         DTC_Register reg;
    6976            0 :         switch (link)
    6977              :         {
    6978            0 :                 case DTC_Link_0:
    6979            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
    6980            0 :                         break;
    6981            0 :                 case DTC_Link_1:
    6982            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
    6983            0 :                         break;
    6984            0 :                 case DTC_Link_2:
    6985            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
    6986            0 :                         break;
    6987            0 :                 case DTC_Link_3:
    6988            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
    6989            0 :                         break;
    6990            0 :                 case DTC_Link_4:
    6991            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
    6992            0 :                         break;
    6993            0 :                 case DTC_Link_5:
    6994            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
    6995            0 :                         break;
    6996            0 :                 case DTC_Link_CFO:
    6997            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
    6998            0 :                         break;
    6999            0 :                 default: {
    7000            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7001            0 :                         __SS_THROW__;
    7002            0 :                 }
    7003              :         }
    7004            0 :         WriteRegister_(1, reg);
    7005            0 : }
    7006              : 
    7007            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink0()
    7008              : {
    7009            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link0);
    7010            0 :         form.description = "SERDES RX PRBS Error Count Link 0";
    7011            0 :         std::stringstream o;
    7012            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_0, form.value);
    7013            0 :         form.vals.push_back(o.str());
    7014            0 :         return form;
    7015            0 : }
    7016            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink1()
    7017              : {
    7018            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link1);
    7019            0 :         form.description = "SERDES RX PRBS Error Count Link 1";
    7020            0 :         std::stringstream o;
    7021            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_1, form.value);
    7022            0 :         form.vals.push_back(o.str());
    7023            0 :         return form;
    7024            0 : }
    7025            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink2()
    7026              : {
    7027            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link2);
    7028            0 :         form.description = "SERDES RX PRBS Error Count Link 2";
    7029            0 :         std::stringstream o;
    7030            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_2, form.value);
    7031            0 :         form.vals.push_back(o.str());
    7032            0 :         return form;
    7033            0 : }
    7034            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink3()
    7035              : {
    7036            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link3);
    7037            0 :         form.description = "SERDES RX PRBS Error Count Link 3";
    7038            0 :         std::stringstream o;
    7039            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_3, form.value);
    7040            0 :         form.vals.push_back(o.str());
    7041            0 :         return form;
    7042            0 : }
    7043            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink4()
    7044              : {
    7045            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link4);
    7046            0 :         form.description = "SERDES RX PRBS Error Count Link 4";
    7047            0 :         std::stringstream o;
    7048            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_4, form.value);
    7049            0 :         form.vals.push_back(o.str());
    7050            0 :         return form;
    7051            0 : }
    7052            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink5()
    7053              : {
    7054            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link5);
    7055            0 :         form.description = "SERDES RX PRBS Error Count Link 5";
    7056            0 :         std::stringstream o;
    7057            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_5, form.value);
    7058            0 :         form.vals.push_back(o.str());
    7059            0 :         return form;
    7060            0 : }
    7061            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountCFOLink()
    7062              : {
    7063            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_CFOLink);
    7064            0 :         form.description = "SERDES RX PRBS Error Count CFO Link";
    7065            0 :         std::stringstream o;
    7066            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_CFO, form.value);
    7067            0 :         form.vals.push_back(o.str());
    7068            0 :         return form;
    7069            0 : }
    7070              : 
    7071            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXCRCErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7072              : {
    7073              :         DTC_Register reg;
    7074            0 :         switch (link)
    7075              :         {
    7076            0 :                 case DTC_Link_0:
    7077            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
    7078            0 :                         break;
    7079            0 :                 case DTC_Link_1:
    7080            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
    7081            0 :                         break;
    7082            0 :                 case DTC_Link_2:
    7083            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
    7084            0 :                         break;
    7085            0 :                 case DTC_Link_3:
    7086            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
    7087            0 :                         break;
    7088            0 :                 case DTC_Link_4:
    7089            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
    7090            0 :                         break;
    7091            0 :                 case DTC_Link_5:
    7092            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
    7093            0 :                         break;
    7094            0 :                 case DTC_Link_CFO:
    7095            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
    7096            0 :                         break;
    7097            0 :                 default: {
    7098            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7099            0 :                         __SS_THROW__;
    7100            0 :                 }
    7101              :         }
    7102            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    7103              : }
    7104            0 : void DTCLib::DTC_Registers::ClearSERDESRXCRCErrorCount(DTC_Link_ID const& link)
    7105              : {
    7106              :         DTC_Register reg;
    7107            0 :         switch (link)
    7108              :         {
    7109            0 :                 case DTC_Link_0:
    7110            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
    7111            0 :                         break;
    7112            0 :                 case DTC_Link_1:
    7113            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
    7114            0 :                         break;
    7115            0 :                 case DTC_Link_2:
    7116            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
    7117            0 :                         break;
    7118            0 :                 case DTC_Link_3:
    7119            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
    7120            0 :                         break;
    7121            0 :                 case DTC_Link_4:
    7122            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
    7123            0 :                         break;
    7124            0 :                 case DTC_Link_5:
    7125            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
    7126            0 :                         break;
    7127            0 :                 case DTC_Link_CFO:
    7128            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
    7129            0 :                         break;
    7130            0 :                 default: {
    7131            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7132            0 :                         __SS_THROW__;
    7133            0 :                 }
    7134              :         }
    7135            0 :         WriteRegister_(1, reg);
    7136            0 : }
    7137              : 
    7138            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink0()
    7139              : {
    7140            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link0);
    7141            0 :         form.description = "SERDES RX CRC Error Count Link 0";
    7142            0 :         std::stringstream o;
    7143            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_0, form.value);
    7144            0 :         form.vals.push_back(o.str());
    7145            0 :         return form;
    7146            0 : }
    7147            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink1()
    7148              : {
    7149            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link1);
    7150            0 :         form.description = "SERDES RX CRC Error Count Link 1";
    7151            0 :         std::stringstream o;
    7152            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_1, form.value);
    7153            0 :         form.vals.push_back(o.str());
    7154            0 :         return form;
    7155            0 : }
    7156            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink2()
    7157              : {
    7158            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link2);
    7159            0 :         form.description = "SERDES RX CRC Error Count Link 2";
    7160            0 :         std::stringstream o;
    7161            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_2, form.value);
    7162            0 :         form.vals.push_back(o.str());
    7163            0 :         return form;
    7164            0 : }
    7165            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink3()
    7166              : {
    7167            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link3);
    7168            0 :         form.description = "SERDES RX CRC Error Count Link 3";
    7169            0 :         std::stringstream o;
    7170            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_3, form.value);
    7171            0 :         form.vals.push_back(o.str());
    7172            0 :         return form;
    7173            0 : }
    7174            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink4()
    7175              : {
    7176            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link4);
    7177            0 :         form.description = "SERDES RX CRC Error Count Link 4";
    7178            0 :         std::stringstream o;
    7179            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_4, form.value);
    7180            0 :         form.vals.push_back(o.str());
    7181            0 :         return form;
    7182            0 : }
    7183            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink5()
    7184              : {
    7185            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link5);
    7186            0 :         form.description = "SERDES RX CRC Error Count Link 5";
    7187            0 :         std::stringstream o;
    7188            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_5, form.value);
    7189            0 :         form.vals.push_back(o.str());
    7190            0 :         return form;
    7191            0 : }
    7192            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountCFOLink()
    7193              : {
    7194            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_CFOLink);
    7195            0 :         form.description = "SERDES RX CRC Error Count CFO Link";
    7196            0 :         std::stringstream o;
    7197            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_CFO, form.value);
    7198            0 :         form.vals.push_back(o.str());
    7199            0 :         return form;
    7200            0 : }
    7201              : 
    7202              : // SERDES RX CRC Error Control
    7203            0 : bool DTCLib::DTC_Registers::ReadEnableInduceSERDESRXCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7204              : {
    7205            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7206            0 :         return dataSet[link];
    7207              : }
    7208            0 : void DTCLib::DTC_Registers::EnableInduceSERDESRXCRCError(DTC_Link_ID const& link)
    7209              : {
    7210            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7211            0 :         dataSet[link] = 1;
    7212            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
    7213            0 : }
    7214            0 : void DTCLib::DTC_Registers::DisableInduceSERDESRXCRCError(DTC_Link_ID const& link)
    7215              : {
    7216            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7217            0 :         dataSet[link] = 0;
    7218            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
    7219            0 : }
    7220            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorControl()
    7221              : {
    7222            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    7223            0 :         form.description = "SERDES RX CRC Error Control";
    7224            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    7225            0 :         for (auto r : DTC_ROC_Links)
    7226            0 :                 form.vals.push_back(std::string("Induce Error Link ") + std::to_string(r) + ":  [" +
    7227            0 :                                                         (ReadEnableInduceSERDESRXCRCError(r, form.value) ? "x" : " ") + "]");
    7228              : 
    7229            0 :         form.vals.push_back(std::string("Incude Error CFO Link: [") +
    7230            0 :                                                 (ReadEnableInduceSERDESRXCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    7231              : 
    7232            0 :         return form;
    7233            0 : }
    7234              : 
    7235            0 : uint32_t DTCLib::DTC_Registers::ReadEVBSERDESRXPacketErrorCounter(std::optional<uint32_t> val)
    7236              : {
    7237            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EBVSERDES_RXPacketErrorCount);
    7238              : }
    7239            0 : void DTCLib::DTC_Registers::ClearEVBSERDESRXPacketErrorCounter()
    7240              : {
    7241            0 :         WriteRegister_(1, DTC_Register_EBVSERDES_RXPacketErrorCount);
    7242            0 : }
    7243            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESRXPacketErrorCounter()
    7244              : {
    7245            0 :         auto form = CreateFormatter(DTC_Register_EBVSERDES_RXPacketErrorCount);
    7246            0 :         form.description = "EVB SERDES RX Packet Error Counter";
    7247            0 :         std::stringstream o;
    7248            0 :         o << std::dec << ReadEVBSERDESRXPacketErrorCounter(form.value);
    7249            0 :         form.vals.push_back(o.str());
    7250            0 :         return form;
    7251            0 : }
    7252              : 
    7253              : // Jitter Attenuator SERDES RX Recovered Clock LOS Counter
    7254            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorRecoveredClockLOSCount(std::optional<uint32_t> val)
    7255              : {
    7256            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7257              : }
    7258            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorRecoveredClockLOSCount()
    7259              : {
    7260            0 :         WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7261            0 : }
    7262            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorRecoveredClockLOSCount()
    7263              : {
    7264            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7265            0 :         form.description = "Jitter Attenuator SERDES RX Recovered Clock LOS Counter";
    7266            0 :         std::stringstream o;
    7267            0 :         o << std::dec << ReadJitterAttenuatorRecoveredClockLOSCount(form.value);
    7268            0 :         form.vals.push_back(o.str());
    7269            0 :         return form;
    7270            0 : }
    7271              : 
    7272              : // Jitter Attenuator SERDES RX External Clock LOS Counter
    7273            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorExternalClockLOSCount(std::optional<uint32_t> val)
    7274              : {
    7275            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7276              : }
    7277            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorExternalClockLOSCount()
    7278              : {
    7279            0 :         WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7280            0 : }
    7281            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorExternalClockLOSCount()
    7282              : {
    7283            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7284            0 :         form.description = "Jitter Attenuator SERDES RX External Clock LOS Counter";
    7285            0 :         std::stringstream o;
    7286            0 :         o << std::dec << ReadJitterAttenuatorExternalClockLOSCount(form.value);
    7287            0 :         form.vals.push_back(o.str());
    7288            0 :         return form;
    7289            0 : }
    7290              : 
    7291              : // ROC Emulator Interpacket Delay
    7292            0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorInterpacketDelay(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7293              : {
    7294              :         DTC_Register reg;
    7295            0 :         switch (link)
    7296              :         {
    7297            0 :                 case DTC_Link_0:
    7298            0 :                         reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
    7299            0 :                         break;
    7300              :                 // case DTC_Link_1:
    7301              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
    7302              :                 //      break;
    7303              :                 // case DTC_Link_2:
    7304              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
    7305              :                 //      break;
    7306              :                 // case DTC_Link_3:
    7307              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
    7308              :                 //      break;
    7309              :                 // case DTC_Link_4:
    7310              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
    7311              :                 //      break;
    7312              :                 // case DTC_Link_5:
    7313              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
    7314              :                 //      break;
    7315            0 :                 default: {
    7316            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7317            0 :                         __SS_THROW__;
    7318            0 :                 }
    7319              :         }
    7320            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    7321              : }
    7322            0 : void DTCLib::DTC_Registers::SetROCEmulatorInterpacketDelay(DTC_Link_ID const& link, uint32_t delay)
    7323              : {
    7324              :         DTC_Register reg;
    7325            0 :         switch (link)
    7326              :         {
    7327            0 :                 case DTC_Link_0:
    7328            0 :                         reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
    7329            0 :                         break;
    7330              :                 // case DTC_Link_1:
    7331              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
    7332              :                 //      break;
    7333              :                 // case DTC_Link_2:
    7334              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
    7335              :                 //      break;
    7336              :                 // case DTC_Link_3:
    7337              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
    7338              :                 //      break;
    7339              :                 // case DTC_Link_4:
    7340              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
    7341              :                 //      break;
    7342              :                 // case DTC_Link_5:
    7343              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
    7344              :                 //      break;
    7345            0 :                 default: {
    7346            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7347            0 :                         __SS_THROW__;
    7348            0 :                 }
    7349              :         }
    7350            0 :         WriteRegister_(delay, reg);
    7351            0 : }
    7352            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink0()
    7353              : {
    7354            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link0);
    7355            0 :         form.description = "ROC Emulator Interpacket Delay all Links (*5ns)";
    7356            0 :         std::stringstream o;
    7357            0 :         o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_0, form.value);
    7358            0 :         form.vals.push_back(o.str());
    7359            0 :         return form;
    7360            0 : }
    7361              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink1()
    7362              : // {
    7363              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link1);
    7364              : //      form.description = "ROC Emulator Interpacket Delay Link 1 (*5ns)";
    7365              : //      std::stringstream o;
    7366              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_1, form.value);
    7367              : //      form.vals.push_back(o.str());
    7368              : //      return form;
    7369              : // }
    7370              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink2()
    7371              : // {
    7372              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link2);
    7373              : //      form.description = "ROC Emulator Interpacket Delay Link 2 (*5ns)";
    7374              : //      std::stringstream o;
    7375              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_2, form.value);
    7376              : //      form.vals.push_back(o.str());
    7377              : //      return form;
    7378              : // }
    7379              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink3()
    7380              : // {
    7381              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link3);
    7382              : //      form.description = "ROC Emulator Interpacket Delay Link 3 (*5ns)";
    7383              : //      std::stringstream o;
    7384              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_3, form.value);
    7385              : //      form.vals.push_back(o.str());
    7386              : //      return form;
    7387              : // }
    7388              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink4()
    7389              : // {
    7390              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link4);
    7391              : //      form.description = "ROC Emulator Interpacket Delay Link 4 (*5ns)";
    7392              : //      std::stringstream o;
    7393              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_4, form.value);
    7394              : //      form.vals.push_back(o.str());
    7395              : //      return form;
    7396              : // }
    7397              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink5()
    7398              : // {
    7399              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link5);
    7400              : //      form.description = "ROC Emulator Interpacket Delay Link 5 (*5ns)";
    7401              : //      std::stringstream o;
    7402              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_5, form.value);
    7403              : //      form.vals.push_back(o.str());
    7404              : //      return form;
    7405              : // }
    7406              : 
    7407              : // TX Data Request Packet Count
    7408            0 : uint32_t DTCLib::DTC_Registers::ReadTXEventWindowMarkerCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7409              : {
    7410            0 :         return val.has_value() ? *val : ReadRegister_(GetTXEventWindowMarkerCountLinkRegister(link));
    7411              : }  // end ReadTXEventWindowMarkerCount()
    7412              : 
    7413            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXEventWindowMarkerCountLink(DTC_Link_ID const& link)
    7414              : {
    7415            0 :         auto form = CreateFormatter(GetTXEventWindowMarkerCountLinkRegister(link));
    7416            0 :         if (link == DTC_Link_CFO)
    7417            0 :                 form.description = "CFO Event Window Marker (EWM) Count";
    7418              :         else
    7419            0 :                 form.description = "EWM TX Count on Link " +
    7420            0 :                                                    std::to_string((GetTXEventWindowMarkerCountLinkRegister(link) -
    7421            0 :                                                                                    GetTXEventWindowMarkerCountLinkRegister(DTC_Link_0)) /
    7422            0 :                                                                                   4);
    7423            0 :         std::stringstream o;
    7424            0 :         o << std::dec << ReadTXEventWindowMarkerCount(link, form.value);
    7425            0 :         form.vals.push_back(o.str());
    7426            0 :         return form;
    7427            0 : }  // end FormatTXEventWindowMarkerCountLink()
    7428              : 
    7429            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXEventWindowMarkerCountLinkRegister(DTC_Link_ID const& link)
    7430              : {
    7431              :         DTC_Register reg;
    7432            0 :         switch (link)
    7433              :         {
    7434            0 :                 case DTC_Link_0:
    7435            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link0;
    7436            0 :                         break;
    7437            0 :                 case DTC_Link_1:
    7438            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link1;
    7439            0 :                         break;
    7440            0 :                 case DTC_Link_2:
    7441            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link2;
    7442            0 :                         break;
    7443            0 :                 case DTC_Link_3:
    7444            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link3;
    7445            0 :                         break;
    7446            0 :                 case DTC_Link_4:
    7447            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link4;
    7448            0 :                         break;
    7449            0 :                 case DTC_Link_5:
    7450            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link5;
    7451            0 :                         break;
    7452            0 :                 case DTC_Link_CFO:
    7453            0 :                         reg = DTC_Register_CFOTXEventWindowMarkerCount_Link6;
    7454            0 :                         break;
    7455            0 :                 default: {
    7456            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7457              :                         ss << "\n\nThe stack trace is as follows:\n"
    7458            0 :                            << otsStyleStackTrace() << __E__;
    7459            0 :                         __SS_THROW__;
    7460            0 :                 }
    7461              :         }
    7462            0 :         return reg;
    7463              : }  // end GetTXEventWindowMarkerCountLinkRegister()
    7464              : 
    7465              : // TX Null Heartbeat Packet Count
    7466            0 : uint32_t DTCLib::DTC_Registers::ReadTXNullHeartbeatCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7467              : {
    7468            0 :         return val.has_value() ? *val : ReadRegister_(GetTXNullHeartbeatCountLinkRegister(link));
    7469              : }  // end ReadTXNullHeartbeatCount()
    7470              : 
    7471            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXNullHeartbeatCountLink(DTC_Link_ID const& link)
    7472              : {
    7473            0 :         auto form = CreateFormatter(GetTXNullHeartbeatCountLinkRegister(link));
    7474            0 :         form.description = "Tx Null HBPs on Link " +
    7475            0 :                                            std::to_string((GetTXNullHeartbeatCountLinkRegister(link) -
    7476            0 :                                                                            GetTXNullHeartbeatCountLinkRegister(DTC_Link_0)) /
    7477            0 :                                                                           4);
    7478            0 :         std::stringstream o;
    7479            0 :         o << std::dec << ReadTXNullHeartbeatCount(link, form.value);
    7480            0 :         form.vals.push_back(o.str());
    7481            0 :         return form;
    7482            0 : }  // end FormatTXNullHeartbeatCountLink()
    7483              : 
    7484            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXNullHeartbeatCountLinkRegister(DTC_Link_ID const& link)
    7485              : {
    7486              :         DTC_Register reg;
    7487            0 :         switch (link)
    7488              :         {
    7489            0 :                 case DTC_Link_0:
    7490            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link0;
    7491            0 :                         break;
    7492            0 :                 case DTC_Link_1:
    7493            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link1;
    7494            0 :                         break;
    7495            0 :                 case DTC_Link_2:
    7496            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link2;
    7497            0 :                         break;
    7498            0 :                 case DTC_Link_3:
    7499            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link3;
    7500            0 :                         break;
    7501            0 :                 case DTC_Link_4:
    7502            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link4;
    7503            0 :                         break;
    7504            0 :                 case DTC_Link_5:
    7505            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link5;
    7506            0 :                         break;
    7507            0 :                 default: {
    7508            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7509              :                         ss << "\n\nThe stack trace is as follows:\n"
    7510            0 :                            << otsStyleStackTrace() << __E__;
    7511            0 :                         __SS_THROW__;
    7512            0 :                 }
    7513              :         }
    7514            0 :         return reg;
    7515              : }  // end GetTXNullHeartbeatCountLinkRegister()
    7516              : 
    7517              : // TX Data Request Packet Count
    7518            0 : uint32_t DTCLib::DTC_Registers::ReadTXDataRequestPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7519              : {
    7520            0 :         return val.has_value() ? *val : ReadRegister_(GetTXDataRequestPacketCountLinkRegister(link));
    7521              : }  // end ReadTXDataRequestPacketCount()
    7522              : 
    7523            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDataRequestPacketCountLink(DTC_Link_ID const& link)
    7524              : {
    7525            0 :         auto form = CreateFormatter(GetTXDataRequestPacketCountLinkRegister(link));
    7526            0 :         form.description = "DRP TX Count on Link " +
    7527            0 :                                            std::to_string((GetTXDataRequestPacketCountLinkRegister(link) -
    7528            0 :                                                                            GetTXDataRequestPacketCountLinkRegister(DTC_Link_0)) /
    7529            0 :                                                                           4);
    7530            0 :         std::stringstream o;
    7531            0 :         o << std::dec << ReadTXDataRequestPacketCount(link, form.value);
    7532            0 :         form.vals.push_back(o.str());
    7533            0 :         return form;
    7534            0 : }  // end FormatTXEventWindowMarkerCountLink()
    7535              : 
    7536            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXDataRequestPacketCountLinkRegister(DTC_Link_ID const& link)
    7537              : {
    7538              :         DTC_Register reg;
    7539            0 :         switch (link)
    7540              :         {
    7541            0 :                 case DTC_Link_0:
    7542            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link0;
    7543            0 :                         break;
    7544            0 :                 case DTC_Link_1:
    7545            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link1;
    7546            0 :                         break;
    7547            0 :                 case DTC_Link_2:
    7548            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link2;
    7549            0 :                         break;
    7550            0 :                 case DTC_Link_3:
    7551            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link3;
    7552            0 :                         break;
    7553            0 :                 case DTC_Link_4:
    7554            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link4;
    7555            0 :                         break;
    7556            0 :                 case DTC_Link_5:
    7557            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link5;
    7558            0 :                         break;
    7559            0 :                 default: {
    7560            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7561              :                         ss << "\n\nThe stack trace is as follows:\n"
    7562            0 :                            << otsStyleStackTrace() << __E__;
    7563            0 :                         __SS_THROW__;
    7564            0 :                 }
    7565              :         }
    7566            0 :         return reg;
    7567              : }  // end GetTXDataRequestPacketCountLinkRegister()
    7568              : 
    7569            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOTXClockMarkerCountLink6()
    7570              : {
    7571            0 :         auto form = CreateFormatter(DTC_Register_CFOTXClockMarkerCount_Link6);
    7572            0 :         form.description = "CFO Clock Marker Count";
    7573            0 :         std::stringstream o;
    7574            0 :         o << std::dec << ReadCFOTXClockMarkerCountLink6(form.value);
    7575            0 :         form.vals.push_back(o.str());
    7576            0 :         return form;
    7577            0 : }  // end FormatCFOTXClockMarkerCountLink6()
    7578              : 
    7579            0 : uint32_t DTCLib::DTC_Registers::ReadCFOTXClockMarkerCountLink6(std::optional<uint32_t> val)
    7580              : {
    7581            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOTXClockMarkerCount_Link6);
    7582              : }  // end ReadCFOTXClockMarkerCountLink6()
    7583              : 
    7584              : // TX Heartbeat Packet Count
    7585            0 : uint32_t DTCLib::DTC_Registers::ReadTXHeartbeatPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7586              : {
    7587            0 :         return val.has_value() ? *val : ReadRegister_(GetTXHeartbeatPacketCountLinkRegister(link));
    7588              : }  // end ReadTXHeartbeatPacketCount()
    7589            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXHeartbeatPacketCountLink(DTC_Link_ID const& link)
    7590              : {
    7591            0 :         auto form = CreateFormatter(GetTXHeartbeatPacketCountLinkRegister(link));
    7592            0 :         if (link == DTC_Link_CFO)
    7593            0 :                 form.description = "CFO Heartbeat Packet (HBP) Count";
    7594              :         else
    7595            0 :                 form.description = "HBP TX Counter Link " +
    7596            0 :                                                    std::to_string((GetTXHeartbeatPacketCountLinkRegister(link) -
    7597            0 :                                                                                    GetTXHeartbeatPacketCountLinkRegister(DTC_Link_0)) /
    7598            0 :                                                                                   4);
    7599            0 :         std::stringstream o;
    7600            0 :         o << std::dec << ReadTXHeartbeatPacketCount(DTC_Link_0, form.value);
    7601            0 :         form.vals.push_back(o.str());
    7602            0 :         return form;
    7603            0 : }  // end FormatTXHeartbeatPacketCountLink()
    7604              : 
    7605            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXHeartbeatPacketCountLinkRegister(DTC_Link_ID const& link)
    7606              : {
    7607              :         DTC_Register reg;
    7608            0 :         switch (link)
    7609              :         {
    7610            0 :                 case DTC_Link_0:
    7611            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link0;
    7612            0 :                         break;
    7613            0 :                 case DTC_Link_1:
    7614            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link1;
    7615            0 :                         break;
    7616            0 :                 case DTC_Link_2:
    7617            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link2;
    7618            0 :                         break;
    7619            0 :                 case DTC_Link_3:
    7620            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link3;
    7621            0 :                         break;
    7622            0 :                 case DTC_Link_4:
    7623            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link4;
    7624            0 :                         break;
    7625            0 :                 case DTC_Link_5:
    7626            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link5;
    7627            0 :                         break;
    7628            0 :                 case DTC_Link_CFO:
    7629            0 :                         reg = DTC_Register_CFOTXHeartbeatPacketCount_Link5;
    7630            0 :                         break;
    7631            0 :                 default: {
    7632            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7633            0 :                         __SS_THROW__;
    7634            0 :                 }
    7635              :         }
    7636            0 :         return reg;
    7637              : }  // end GetTXHeartbeatPacketCountLinkRegister()
    7638              : 
    7639              : // RX Data Header Packet Count
    7640            0 : uint32_t DTCLib::DTC_Registers::ReadRXDataHeaderPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7641              : {
    7642            0 :         return val.has_value() ? *val : ReadRegister_(GetRXDataHeaderPacketCountLinkRegister(link));
    7643              : }  // end ReadRXDataHeaderPacketCount()
    7644              : 
    7645            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataHeaderPacketCountLink(DTC_Link_ID const& link)
    7646              : {
    7647            0 :         auto form = CreateFormatter(GetRXDataHeaderPacketCountLinkRegister(link));
    7648            0 :         form.description = "ROC DH RX Count on Link " +
    7649            0 :                                            std::to_string((GetRXDataHeaderPacketCountLinkRegister(link) -
    7650            0 :                                                                            GetRXDataHeaderPacketCountLinkRegister(DTC_Link_0)) /
    7651            0 :                                                                           4);
    7652            0 :         std::stringstream o;
    7653            0 :         o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
    7654            0 :         form.vals.push_back(o.str());
    7655            0 :         return form;
    7656            0 : }  // end FormatRXDataHeaderPacketCountLink()
    7657              : 
    7658            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataHeaderPacketCountLinkRegister(DTC_Link_ID const& link)
    7659              : {
    7660              :         DTC_Register reg;
    7661            0 :         switch (link)
    7662              :         {
    7663            0 :                 case DTC_Link_0:
    7664            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link0;
    7665            0 :                         break;
    7666            0 :                 case DTC_Link_1:
    7667            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link1;
    7668            0 :                         break;
    7669            0 :                 case DTC_Link_2:
    7670            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link2;
    7671            0 :                         break;
    7672            0 :                 case DTC_Link_3:
    7673            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link3;
    7674            0 :                         break;
    7675            0 :                 case DTC_Link_4:
    7676            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link4;
    7677            0 :                         break;
    7678            0 :                 case DTC_Link_5:
    7679            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link5;
    7680            0 :                         break;
    7681            0 :                 default: {
    7682            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7683            0 :                         __SS_THROW__;
    7684            0 :                 }
    7685              :         }
    7686            0 :         return reg;
    7687              : }  // end GetRXDataHeaderPacketCountLinkRegister()
    7688              : 
    7689              : // CFO CDC Diagnostic (Parity Mismatch & Batch Slip Counts)
    7690            0 : uint32_t DTCLib::DTC_Registers::ReadCFOCDCDiag(std::optional<uint32_t> val)
    7691              : {
    7692            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOCDCDiag);
    7693              : }
    7694              : 
    7695            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOCDCDiag()
    7696              : {
    7697            0 :         auto form = CreateFormatter(DTC_Register_CFOCDCDiag);
    7698            0 :         form.description = "CFO CDC Diagnostic";
    7699            0 :         uint32_t parityMismatchCount = (form.value >> 16) & 0xFFFF;
    7700            0 :         uint32_t batchSlipCount = form.value & 0xFFFF;
    7701            0 :         form.vals.push_back(std::string("Parity Mismatch Count: ") + std::to_string(parityMismatchCount));
    7702            0 :         form.vals.push_back(std::string("Batch Slip Count:      ") + std::to_string(batchSlipCount));
    7703            0 :         return form;
    7704            0 : }
    7705              : 
    7706              : // EVB High Level Counters (0x9200/0x9204/0x9208), each holding two 16-bit word counters
    7707              : /// @brief Read the EVB firmware version from 0x9200 [15:0].
    7708              : ///        Encoded as 0xTMmm where T is type (B = EVBuilding), M is major, mm is minor.
    7709            0 : std::string DTCLib::DTC_Registers::ReadEVBFirmwareVersion(std::optional<uint32_t> val)
    7710              : {
    7711            0 :         uint16_t ver = ReadEVBROCInputWords(val);
    7712            0 :         char type = static_cast<char>((ver >> 12) & 0xF);
    7713            0 :         int major = (ver >> 8) & 0xF;
    7714            0 :         int minor = ver & 0xFF;
    7715            0 :         std::ostringstream o;
    7716            0 :         o << std::hex << std::uppercase << type << std::dec << major << "." << std::setw(2) << std::setfill('0') << minor;
    7717            0 :         return o.str();
    7718            0 : }  // end ReadEVBFirmwareVersion()
    7719              : 
    7720              : /// @brief Override to append EVB firmware version to the time-alive line when present.
    7721            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDeviceTimeAlive()
    7722              : {
    7723            0 :         auto form = CFOandDTC_Registers::FormatDeviceTimeAlive();
    7724            0 :         uint16_t evbRaw = ReadEVBROCInputWords();
    7725            0 :         uint8_t typeNibble = (evbRaw >> 12) & 0xF;
    7726            0 :         if (typeNibble == 0xB)  // 'B' = EVB firmware present
    7727              :         {
    7728            0 :                 auto& line = form.vals.back();
    7729            0 :                 auto pos = line.find("-ROC");
    7730            0 :                 if (pos == std::string::npos)
    7731            0 :                         pos = line.find("-Links");
    7732            0 :                 if (pos != std::string::npos)
    7733              :                 {
    7734            0 :                         while (pos > 0 && line[pos - 1] != ' ')
    7735            0 :                                 --pos;
    7736            0 :                         line.insert(pos, "EVB  ");
    7737              :                 }
    7738              :                 else
    7739            0 :                         line += ", EVB";
    7740              :         }
    7741            0 :         return form;
    7742            0 : }  // end DTC_Registers::FormatDeviceTimeAlive()
    7743              : 
    7744            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters0(std::optional<uint32_t> val)
    7745              : {
    7746            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters0);
    7747              : }  // end ReadEVBHighLevelCounters0()
    7748              : 
    7749            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters1(std::optional<uint32_t> val)
    7750              : {
    7751            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters1);
    7752              : }  // end ReadEVBHighLevelCounters1()
    7753              : 
    7754            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters2(std::optional<uint32_t> val)
    7755              : {
    7756            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters2);
    7757              : }  // end ReadEVBHighLevelCounters2()
    7758              : 
    7759            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters3(std::optional<uint32_t> val)
    7760              : {
    7761            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters3);
    7762              : }  // end ReadEVBHighLevelCounters3()
    7763              : 
    7764              : /// @brief 0x9200 [15:0] - ROC input words
    7765            0 : uint16_t DTCLib::DTC_Registers::ReadEVBROCInputWords(std::optional<uint32_t> val)
    7766              : {
    7767            0 :         return ReadEVBHighLevelCounters0(val) & 0xFFFF;
    7768              : }  // end ReadEVBROCInputWords()
    7769              : 
    7770              : /// @brief 0x9200 [31:16] - Self-transfer words
    7771            0 : uint16_t DTCLib::DTC_Registers::ReadEVBSelfTransferWords(std::optional<uint32_t> val)
    7772              : {
    7773            0 :         return (ReadEVBHighLevelCounters0(val) >> 16) & 0xFFFF;
    7774              : }  // end ReadEVBSelfTransferWords()
    7775              : 
    7776              : /// @brief 0x9204 [15:0] - DDR FIFO write words
    7777            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDDRFIFOWriteWords(std::optional<uint32_t> val)
    7778              : {
    7779            0 :         return ReadEVBHighLevelCounters1(val) & 0xFFFF;
    7780              : }  // end ReadEVBDDRFIFOWriteWords()
    7781              : 
    7782              : /// @brief 0x9204 [31:16] - DDR->TX words
    7783            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDDRToTXWords(std::optional<uint32_t> val)
    7784              : {
    7785            0 :         return (ReadEVBHighLevelCounters1(val) >> 16) & 0xFFFF;
    7786              : }  // end ReadEVBDDRToTXWords()
    7787              : 
    7788              : /// @brief 0x9208 [15:0] - Buffer manager output words
    7789            0 : uint16_t DTCLib::DTC_Registers::ReadEVBBufferManagerOutputWords(std::optional<uint32_t> val)
    7790              : {
    7791            0 :         return ReadEVBHighLevelCounters2(val) & 0xFFFF;
    7792              : }  // end ReadEVBBufferManagerOutputWords()
    7793              : 
    7794              : /// @brief 0x9208 [31:16] - DMA output words
    7795            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDMAOutputWords(std::optional<uint32_t> val)
    7796              : {
    7797            0 :         return (ReadEVBHighLevelCounters2(val) >> 16) & 0xFFFF;
    7798              : }  // end ReadEVBDMAOutputWords()
    7799              : 
    7800              : /// @brief 0x920C [15:0] - GBE RX words
    7801            0 : uint16_t DTCLib::DTC_Registers::ReadEVBGBERXWords(std::optional<uint32_t> val)
    7802              : {
    7803            0 :         return ReadEVBHighLevelCounters3(val) & 0xFFFF;
    7804              : }  // end ReadEVBGBERXWords()
    7805              : 
    7806              : // RX Data Packet Count
    7807            0 : uint32_t DTCLib::DTC_Registers::ReadRXDataPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7808              : {
    7809            0 :         return val.has_value() ? *val : ReadRegister_(GetRXDataPacketCountLinkRegister(link));
    7810              : }  // end ReadRXDataPacketCount()
    7811              : 
    7812            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataPacketCountLink(DTC_Link_ID const& link)
    7813              : {
    7814            0 :         auto form = CreateFormatter(GetRXDataPacketCountLinkRegister(link));
    7815            0 :         form.description = "ROC DP RX Count on Link " +
    7816            0 :                                            std::to_string((GetRXDataPacketCountLinkRegister(link) -
    7817            0 :                                                                            GetRXDataPacketCountLinkRegister(DTC_Link_0)) /
    7818            0 :                                                                           4);
    7819            0 :         std::stringstream o;
    7820            0 :         o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
    7821            0 :         form.vals.push_back(o.str());
    7822            0 :         return form;
    7823            0 : }  // end FormatRXDataPacketCountLink()
    7824              : 
    7825            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataPacketCountLinkRegister(DTC_Link_ID const& link)
    7826              : {
    7827              :         DTC_Register reg;
    7828            0 :         switch (link)
    7829              :         {
    7830            0 :                 case DTC_Link_0:
    7831            0 :                         reg = DTC_Register_RXDataPacketCount_Link0;
    7832            0 :                         break;
    7833            0 :                 case DTC_Link_1:
    7834            0 :                         reg = DTC_Register_RXDataPacketCount_Link1;
    7835            0 :                         break;
    7836            0 :                 case DTC_Link_2:
    7837            0 :                         reg = DTC_Register_RXDataPacketCount_Link2;
    7838            0 :                         break;
    7839            0 :                 case DTC_Link_3:
    7840            0 :                         reg = DTC_Register_RXDataPacketCount_Link3;
    7841            0 :                         break;
    7842            0 :                 case DTC_Link_4:
    7843            0 :                         reg = DTC_Register_RXDataPacketCount_Link4;
    7844            0 :                         break;
    7845            0 :                 case DTC_Link_5:
    7846            0 :                         reg = DTC_Register_RXDataPacketCount_Link5;
    7847            0 :                         break;
    7848            0 :                 default: {
    7849            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7850            0 :                         __SS_THROW__;
    7851            0 :                 }
    7852              :         }
    7853            0 :         return reg;
    7854              : }  // end GetRXDataPacketCountLinkRegister()
    7855              : 
    7856              : // EVB Diagnostic RX Packet FIFO
    7857            0 : uint64_t DTCLib::DTC_Registers::ReadEVBDiagnosticFIFO(std::optional<uint32_t> val)
    7858              : {
    7859            0 :         uint64_t ret = val.has_value() ? *val : ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_High);
    7860            0 :         ret = (ret << 32) + ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_Low);
    7861            0 :         return ret;
    7862              : }
    7863            0 : void DTCLib::DTC_Registers::ClearEVBDiagnosticFIFO()
    7864              : {
    7865            0 :         WriteRegister_(0, DTC_Register_EVBDiagnosticRXPacket_Low);
    7866            0 : }
    7867              : 
    7868              : // Event Mode Lookup Table
    7869              : /// <summary>
    7870              : /// Set all event mode words to the given value
    7871              : /// </summary>
    7872              : /// <param name="data">Value for all event mode words</param>
    7873            0 : void DTCLib::DTC_Registers::SetAllEventModeWords(uint32_t data)
    7874              : {
    7875            0 :         for (uint16_t address = DTC_Register_EventModeLookupTableStart; address <= DTC_Register_EventModeLookupTableEnd;
    7876            0 :                  address += 4)
    7877              :         {
    7878            0 :                 auto retry = 3;
    7879              :                 int errorCode;
    7880              :                 do
    7881              :                 {
    7882            0 :                         errorCode = device_.write_register(address, 100, data);
    7883            0 :                         --retry;
    7884            0 :                 } while (retry > 0 && errorCode != 0);
    7885            0 :                 if (errorCode != 0)
    7886              :                 {
    7887            0 :                         __SS__ << "Error writing register " << address;
    7888            0 :                         __SS_THROW__;
    7889              :                         // throw DTC_IOErrorException(errorCode);
    7890            0 :                 }
    7891              :         }
    7892            0 : }
    7893              : 
    7894              : /// <summary>
    7895              : /// Set a given event mode word
    7896              : /// </summary>
    7897              : /// <param name="which">Word index to write</param>
    7898              : /// <param name="data">Data for word</param>
    7899            0 : void DTCLib::DTC_Registers::SetEventModeWord(uint8_t which, uint32_t data)
    7900              : {
    7901            0 :         uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
    7902            0 :         if (address <= DTC_Register_EventModeLookupTableEnd)
    7903              :         {
    7904            0 :                 auto retry = 3;
    7905              :                 int errorCode;
    7906              :                 do
    7907              :                 {
    7908            0 :                         errorCode = device_.write_register(address, 100, data);
    7909            0 :                         --retry;
    7910            0 :                 } while (retry > 0 && errorCode != 0);
    7911            0 :                 if (errorCode != 0)
    7912              :                 {
    7913            0 :                         __SS__ << "Error writing register " << address;
    7914            0 :                         __SS_THROW__;
    7915              :                         // throw DTC_IOErrorException(errorCode);
    7916            0 :                 }
    7917              :         }
    7918            0 : }
    7919              : 
    7920              : /// <summary>
    7921              : /// Read an event mode word from the Event Mode lookup table
    7922              : /// </summary>
    7923              : /// <param name="which">Word index to read</param>
    7924              : /// <returns>Value of the given event mode word</returns>
    7925            0 : uint32_t DTCLib::DTC_Registers::ReadEventModeWord(uint8_t which)
    7926              : {
    7927            0 :         uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
    7928            0 :         if (address <= DTC_Register_EventModeLookupTableEnd)
    7929              :         {
    7930            0 :                 auto retry = 3;
    7931              :                 int errorCode;
    7932              :                 uint32_t data;
    7933              :                 do
    7934              :                 {
    7935            0 :                         errorCode = device_.read_register(address, 100, &data);
    7936            0 :                         --retry;
    7937            0 :                 } while (retry > 0 && errorCode != 0);
    7938            0 :                 if (errorCode != 0)
    7939              :                 {
    7940            0 :                         __SS__ << "Error writing register " << address;
    7941            0 :                         __SS_THROW__;
    7942              :                         // throw DTC_IOErrorException(errorCode);
    7943            0 :                 }
    7944              : 
    7945            0 :                 return data;
    7946              :         }
    7947            0 :         return 0;
    7948              : }
    7949              : 
    7950              : // Oscillator Programming (DDR and SERDES)
    7951              : /// <summary>
    7952              : /// Set the given oscillator to the given frequency, calculating a new program in the process.
    7953              : /// </summary>
    7954              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    7955              : /// <param name="targetFrequency">New frequency to program, in Hz</param>
    7956              : /// <returns>Whether the oscillator was changed (Will not reset if already set to desired frequency)</returns>
    7957            0 : bool DTCLib::DTC_Registers::SetNewOscillatorFrequency(DTC_OscillatorType oscillator, double targetFrequency)
    7958              : {
    7959            0 :         auto currentFrequency = 0;  // As of 2023 DTCs, can not read frequency back (it was doing nothing, just a scratch register) // ReadCurrentFrequency(oscillator);
    7960            0 :         auto currentProgram = ReadCurrentProgram(oscillator);
    7961            0 :         __COUT__ << "Target Frequency: " << targetFrequency << ", Current Frequency: " << currentFrequency
    7962            0 :                          << ", Current Program: " << std::showbase << std::hex << currentProgram;
    7963              : 
    7964              :         // Check if targetFrequency is essentially the same as the current frequency...
    7965            0 :         if (fabs(currentFrequency - targetFrequency) < targetFrequency * 30 / 1000000)
    7966              :         {
    7967            0 :                 __COUT_INFO__ << "New frequency and old frequency are within 30 ppm of each other, not reprogramming!";
    7968            0 :                 return false;
    7969              :         }
    7970              : 
    7971            0 :         auto newParameters = CalculateFrequencyForProgramming_(targetFrequency, currentFrequency, currentProgram);
    7972            0 :         if (newParameters == 0)
    7973              :         {
    7974            0 :                 __COUT_WARN__ << "New program calculated as 0! Check parameters!";
    7975            0 :                 return false;
    7976              :         }
    7977            0 :         WriteCurrentProgram(newParameters, oscillator);
    7978              :         // WriteCurrentFrequency(targetFrequency, oscillator); //As of 2023 DTCs, can not write frequency back (it was doing nothing, just a scratch register)
    7979            0 :         return true;
    7980              : }
    7981              : 
    7982              : /// <summary>
    7983              : /// Read the current RFREQ and dividers of the given oscillator clock
    7984              : /// </summary>
    7985              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    7986              : /// <returns>64-bit integer contianing current oscillator program</returns>
    7987            0 : uint64_t DTCLib::DTC_Registers::ReadCurrentProgram(DTC_OscillatorType oscillator)
    7988              : {
    7989            0 :         switch (oscillator)
    7990              :         {
    7991            0 :                 case DTC_OscillatorType_SERDES:
    7992            0 :                         return ReadSERDESOscillatorParameters_();
    7993            0 :                 case DTC_OscillatorType_Timing:
    7994            0 :                         return ReadTimingOscillatorParameters_();
    7995              :                 // case DTC_OscillatorType_DDR:
    7996              :                 //      return ReadDDROscillatorParameters_();
    7997            0 :                 default:
    7998            0 :                         __SS__ << "Invalid DTC_OscillatorType to read: " + std::to_string(oscillator);
    7999            0 :                         __SS_THROW__;
    8000              :         }
    8001              :         return 0;
    8002              : }
    8003              : 
    8004              : /// <summary>
    8005              : /// Writes a program for the given oscillator crystal. This function should be paired with a call to
    8006              : /// WriteCurrentFrequency so that subsequent programming attempts work as expected.
    8007              : /// </summary>
    8008              : /// <param name="program">64-bit integer with new RFREQ and dividers</param>
    8009              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    8010            0 : void DTCLib::DTC_Registers::WriteCurrentProgram(uint64_t program, DTC_OscillatorType oscillator)
    8011              : {
    8012            0 :         switch (oscillator)
    8013              :         {
    8014            0 :                 case DTC_OscillatorType_SERDES:
    8015            0 :                         SetSERDESOscillatorParameters_(program);
    8016            0 :                         break;
    8017            0 :                 case DTC_OscillatorType_Timing:
    8018            0 :                         SetTimingOscillatorParameters_(program);
    8019            0 :                         break;
    8020              :                 // case DTC_OscillatorType_DDR:
    8021              :                 //      SetDDROscillatorParameters_(program);
    8022              :                 //      break;
    8023            0 :                 default:
    8024            0 :                         __SS__ << "Invalid DTC_OscillatorType to program: " + std::to_string(oscillator);
    8025            0 :                         __SS_THROW__;
    8026              :         }
    8027            0 : }
    8028              : 
    8029              : // Private Functions
    8030            0 : void DTCLib::DTC_Registers::VerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite)
    8031              : {
    8032              :         // verify register readback
    8033              :         if (1)
    8034              :         {
    8035              :                 // uint32_t readbackReturnValue = ReadRegister_(address);
    8036              :                 // uint32_t readbackValue = readbackReturnValue;
    8037              :                 // uint32_t readbackValue = ReadRegister_(address);
    8038              : 
    8039            0 :                 switch (address)  // handle special register checks by masking of DONT-CARE bits, or else check full 32 bits
    8040              :                 {
    8041              :                         //---------- DTC only registers
    8042            0 :                         case DTC_Register_CFOLinkErrorFlags:  // CFO Sample Permanent Offset 2:0
    8043            0 :                                 dataToWrite &= 0x03;
    8044            0 :                                 readbackValue &= 0x03;
    8045            0 :                                 break;
    8046            0 :                         case DTC_Register_CFOMarkerEnables:  // CFO emulator marker enables: 5:0 enables clock marker, 13:8 is event
    8047              :                                                                                                  // marker per ROC link for some reason, now event marker is not returned
    8048              :                                                                                                  // (FIXME?)
    8049            0 :                                 dataToWrite &= 0x03f;
    8050            0 :                                 readbackValue &= 0x03f;
    8051            0 :                                 break;
    8052            0 :                         case DTC_Register_RXCDRUnlockCount_CFOLink:  // write clears 32-bit CDR unlock counter, but can read back errors
    8053              :                                                                                                                  // immediately, so don't check
    8054              :                         case DTC_Register_JitterAttenuatorLossOfLockCount:
    8055              :                         case DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount:
    8056              :                         case DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount:
    8057            0 :                                 return;
    8058            0 :                         case DTC_Register_JitterAttenuatorCSR:  // 0x9308 bit-0 is reset, input select bit-5:4, bit-8 is LOL, bit-11:9
    8059              :                                                                                                         // (input LOS).. only check input select bits
    8060            0 :                                 dataToWrite &= (3 << 4);
    8061            0 :                                 readbackValue &= (3 << 4);
    8062            0 :                                 break;
    8063            0 :                         case DTC_Register_CFOEmulation_EventMode2:  // only lower 16-bits are R/W
    8064            0 :                                 dataToWrite &= 0x0000ffff;
    8065            0 :                                 readbackValue &= 0x0000ffff;
    8066            0 :                                 break;
    8067            0 :                         case DTC_Register_DetEmulation_Control1:  // self clearing bit-1, so return immediately
    8068            0 :                                 return;
    8069            0 :                         case DTC_Register_EVBStats:  // addrs for write, data on read
    8070            0 :                                 return;
    8071              : 
    8072            0 :                         default:;  // do direct comparison of each bit
    8073              :                 }              // end readback verification address case handling
    8074              : 
    8075            0 :                 if (readbackValue != dataToWrite)
    8076              :                 {
    8077              :                         try
    8078              :                         {
    8079            0 :                                 __SS__ << "Write check mismatch - "
    8080            0 :                                            << "write value 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(dataToWrite)
    8081            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
    8082            0 :                                            << std::endl
    8083            0 :                                            << "If you do not understand this error, try checking the DTC firmware version: " << ReadDesignDate() << std::endl;
    8084            0 :                                 __SS_ONLY_THROW__;
    8085            0 :                         }
    8086            0 :                         catch (const std::runtime_error& e)
    8087              :                         {
    8088            0 :                                 std::stringstream ss;
    8089            0 :                                 ss << e.what();
    8090              :                                 ss << "\n\nThe stack trace is as follows:\n"
    8091            0 :                                    << otsStyleStackTrace() << __E__;
    8092            0 :                                 __SS_THROW__;
    8093            0 :                         }
    8094              :                 }
    8095              :                 // return readbackReturnValue;
    8096              :         }  // end verify register readback
    8097              : }  // end VerifyRegisterWrite_()
    8098              : 
    8099            0 : int DTCLib::DTC_Registers::DecodeHighSpeedDivider_(int input)
    8100              : {
    8101            0 :         switch (input)
    8102              :         {
    8103            0 :                 case 0:
    8104            0 :                         return 4;
    8105            0 :                 case 1:
    8106            0 :                         return 5;
    8107            0 :                 case 2:
    8108            0 :                         return 6;
    8109            0 :                 case 3:
    8110            0 :                         return 7;
    8111            0 :                 case 5:
    8112            0 :                         return 9;
    8113            0 :                 case 7:
    8114            0 :                         return 11;
    8115            0 :                 default:
    8116            0 :                         return -1;
    8117              :         }
    8118              : }
    8119              : 
    8120            0 : int DTCLib::DTC_Registers::EncodeHighSpeedDivider_(int input)
    8121              : {
    8122            0 :         switch (input)
    8123              :         {
    8124            0 :                 case 4:
    8125            0 :                         return 0;
    8126            0 :                 case 5:
    8127            0 :                         return 1;
    8128            0 :                 case 6:
    8129            0 :                         return 2;
    8130            0 :                 case 7:
    8131            0 :                         return 3;
    8132            0 :                 case 9:
    8133            0 :                         return 5;
    8134            0 :                 case 11:
    8135            0 :                         return 7;
    8136            0 :                 default:
    8137            0 :                         return -1;
    8138              :         }
    8139              : }
    8140              : 
    8141            0 : int DTCLib::DTC_Registers::EncodeOutputDivider_(int input)
    8142              : {
    8143            0 :         if (input == 1) return 0;
    8144            0 :         int temp = input / 2;
    8145            0 :         return (temp * 2) - 1;
    8146              : }
    8147              : 
    8148            0 : uint64_t DTCLib::DTC_Registers::CalculateFrequencyForProgramming_(double targetFrequency, double currentFrequency,
    8149              :                                                                                                                                   uint64_t currentProgram)
    8150              : {
    8151            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: targetFrequency=" << targetFrequency << ", currentFrequency=" << currentFrequency
    8152            0 :                                                          << ", currentProgram=" << std::showbase << std::hex << static_cast<unsigned long long>(currentProgram);
    8153            0 :         auto currentHighSpeedDivider = DecodeHighSpeedDivider_((currentProgram >> 45) & 0x7);
    8154            0 :         auto currentOutputDivider = DecodeOutputDivider_((currentProgram >> 38) & 0x7F);
    8155            0 :         auto currentRFREQ = DecodeRFREQ_(currentProgram & 0x3FFFFFFFFF);
    8156            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Current HSDIV=" << currentHighSpeedDivider << ", N1=" << currentOutputDivider << ", RFREQ=" << currentRFREQ;
    8157            0 :         const auto minFreq = 4850000000;  // Hz
    8158            0 :         const auto maxFreq = 5670000000;  // Hz
    8159              : 
    8160            0 :         auto fXTAL = currentFrequency * currentHighSpeedDivider * currentOutputDivider / currentRFREQ;
    8161            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: fXTAL=" << fXTAL;
    8162              : 
    8163            0 :         std::vector<int> hsdiv_values = {11, 9, 7, 6, 5, 4};
    8164            0 :         std::vector<std::pair<int, double>> parameter_values;
    8165            0 :         for (auto hsdiv : hsdiv_values)
    8166              :         {
    8167            0 :                 auto minN = minFreq / (targetFrequency * hsdiv);
    8168            0 :                 if (minN > 128) break;
    8169              : 
    8170            0 :                 auto thisN = 2;
    8171            0 :                 if (minN < 1) thisN = 1;
    8172            0 :                 while (thisN < minN)
    8173              :                 {
    8174            0 :                         thisN += 2;
    8175              :                 }
    8176            0 :                 auto fdco_new = hsdiv * thisN * targetFrequency;
    8177            0 :                 TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Adding solution: HSDIV=" << hsdiv << ", N1=" << thisN << ", fdco_new=" << fdco_new;
    8178            0 :                 parameter_values.push_back(std::make_pair(thisN, fdco_new));
    8179              :         }
    8180              : 
    8181            0 :         auto counter = -1;
    8182            0 :         auto newHighSpeedDivider = 0;
    8183            0 :         auto newOutputDivider = 0;
    8184            0 :         auto newRFREQ = 0.0;
    8185              : 
    8186            0 :         for (auto values : parameter_values)
    8187              :         {
    8188            0 :                 ++counter;
    8189            0 :                 if (values.second > maxFreq) continue;
    8190              : 
    8191            0 :                 newHighSpeedDivider = hsdiv_values[counter];
    8192            0 :                 newOutputDivider = values.first;
    8193            0 :                 newRFREQ = values.second / fXTAL;
    8194            0 :                 break;
    8195              :         }
    8196            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: HSDIV=" << newHighSpeedDivider << ", N1=" << newOutputDivider << ", RFREQ=" << newRFREQ;
    8197              : 
    8198            0 :         if (EncodeHighSpeedDivider_(newHighSpeedDivider) == -1)
    8199              :         {
    8200            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid HSDIV " << newHighSpeedDivider << "!";
    8201            0 :                 return 0;
    8202              :         }
    8203            0 :         if (newOutputDivider > 128 || newOutputDivider < 0)
    8204              :         {
    8205            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid N1 " << newOutputDivider << "!";
    8206            0 :                 return 0;
    8207              :         }
    8208            0 :         if (newRFREQ <= 0)
    8209              :         {
    8210            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid RFREQ " << newRFREQ << "!";
    8211            0 :                 return 0;
    8212              :         }
    8213              : 
    8214            0 :         auto output = (static_cast<uint64_t>(EncodeHighSpeedDivider_(newHighSpeedDivider)) << 45) +
    8215            0 :                                   (static_cast<uint64_t>(EncodeOutputDivider_(newOutputDivider)) << 38) + EncodeRFREQ_(newRFREQ);
    8216            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: " << std::showbase << std::hex << static_cast<unsigned long long>(output);
    8217            0 :         return output;
    8218            0 : }
    8219              : 
    8220            0 : uint64_t DTCLib::DTC_Registers::ReadSERDESOscillatorParameters_()
    8221              : {
    8222            0 :         uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7)) << 40) +
    8223            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8)) << 32) +
    8224            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9)) << 24) +
    8225            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10)) << 16) +
    8226            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11)) << 8) +
    8227            0 :                                         static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12));
    8228            0 :         return data;
    8229              : }
    8230              : 
    8231            0 : uint64_t DTCLib::DTC_Registers::ReadTimingOscillatorParameters_()
    8232              : {
    8233            0 :         uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7)) << 40) +
    8234            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8)) << 32) +
    8235            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9)) << 24) +
    8236            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10)) << 16) +
    8237            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11)) << 8) +
    8238            0 :                                         static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12));
    8239            0 :         return data;
    8240              : }
    8241              : 
    8242              : // uint64_t DTCLib::DTC_Registers::ReadDDROscillatorParameters_()
    8243              : // {
    8244              : //      uint64_t data = (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7)) << 40) +
    8245              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8)) << 32) +
    8246              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9)) << 24) +
    8247              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10)) << 16) +
    8248              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11)) << 8) +
    8249              : //                                      static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12));
    8250              : //      return data;
    8251              : // }
    8252              : 
    8253            0 : void DTCLib::DTC_Registers::SetSERDESOscillatorParameters_(uint64_t program)
    8254              : {
    8255            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0x10);
    8256              : 
    8257            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7, static_cast<uint8_t>(program >> 40));
    8258            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8, static_cast<uint8_t>(program >> 32));
    8259            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9, static_cast<uint8_t>(program >> 24));
    8260            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10, static_cast<uint8_t>(program >> 16));
    8261            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11, static_cast<uint8_t>(program >> 8));
    8262            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12, static_cast<uint8_t>(program));
    8263              : 
    8264            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0);
    8265            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x87, 0x40);
    8266            0 : }
    8267              : 
    8268            0 : void DTCLib::DTC_Registers::SetTimingOscillatorParameters_(uint64_t program)
    8269              : {
    8270            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0x10);
    8271              : 
    8272            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7, static_cast<uint8_t>(program >> 40));
    8273            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8, static_cast<uint8_t>(program >> 32));
    8274            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9, static_cast<uint8_t>(program >> 24));
    8275            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10, static_cast<uint8_t>(program >> 16));
    8276            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11, static_cast<uint8_t>(program >> 8));
    8277            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12, static_cast<uint8_t>(program));
    8278              : 
    8279            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0);
    8280            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x87, 0x40);
    8281            0 : }
    8282              : 
    8283              : // void DTCLib::DTC_Registers::SetDDROscillatorParameters_(uint64_t program)
    8284              : // {
    8285              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0x10);
    8286              : 
    8287              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7, static_cast<uint8_t>(program >> 40));
    8288              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8, static_cast<uint8_t>(program >> 32));
    8289              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9, static_cast<uint8_t>(program >> 24));
    8290              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10, static_cast<uint8_t>(program >> 16));
    8291              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11, static_cast<uint8_t>(program >> 8));
    8292              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12, static_cast<uint8_t>(program));
    8293              : 
    8294              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0);
    8295              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x87, 0x40);
    8296              : // }
    8297              : 
    8298            0 : bool DTCLib::DTC_Registers::WaitForLinkReady_(DTC_Link_ID const& link, size_t interval, double timeout /*seconds*/)
    8299              : {
    8300            0 :         auto start = std::chrono::steady_clock::now();
    8301            0 :         auto last_print = start;
    8302            0 :         bool ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
    8303              : 
    8304            0 :         while (!ready)
    8305              :         {
    8306            0 :                 usleep(interval);
    8307            0 :                 ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
    8308            0 :                 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - last_print).count() > 5.0)
    8309              :                 {
    8310            0 :                         __COUT__ << "DTC_Registers: WaitForLinkReady_: ROC Link " << link << ": PLL Locked: " << std::boolalpha << ReadSERDESPLLLocked(link) << ", RX Reset Done: " << ReadResetRXSERDESDone(link) << ", TX Reset Done: " << ReadResetTXSERDESDone(link) << ", CDR Lock: " << ReadSERDESRXCDRLock(link);
    8311            0 :                         last_print = std::chrono::steady_clock::now();
    8312              :                 }
    8313            0 :                 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - start).count() > timeout)
    8314              :                 {
    8315            0 :                         __COUT_ERR__ << "DTC_Registers: WaitForLinkReady_ ABORTING: ROC Link " << link << ": PLL Locked: " << std::boolalpha << ReadSERDESPLLLocked(link) << ", RX Reset Done: " << ReadResetRXSERDESDone(link) << ", TX Reset Done: " << ReadResetTXSERDESDone(link) << ", CDR Lock: " << ReadSERDESRXCDRLock(link);
    8316            0 :                         return false;
    8317              :                 }
    8318              :         }
    8319            0 :         return true;
    8320              : }
        

Generated by: LCOV version 2.0-1