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

Generated by: LCOV version 2.0-1