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 % 4846 0
Test Date: 2026-10-29 01:38:59 Functions: 0.0 % 703 0

            Line data    Source code
       1              : #include "DTC_Registers.h"
       2              : #include "EVBErrorStatus.h"
       3              : 
       4              : #include <assert.h>
       5              : #include <unistd.h>
       6              : #include <chrono>
       7              : #include <cmath>
       8              : #include <iomanip>  // std::setw, std::setfill
       9              : #include <sstream>  // Convert uint to hex string
      10              : 
      11              : #include "TRACE/tracemf.h"
      12              : 
      13              : #define TLVL_ResetDTC TLVL_DEBUG + 5
      14              : #define TLVL_AutogenDRP TLVL_DEBUG + 6
      15              : #define TLVL_SERDESReset TLVL_DEBUG + 7
      16              : #define TLVL_CalculateFreq TLVL_DEBUG + 8
      17              : #define TLVL_Detail TLVL_DEBUG + 11
      18              : #define TLVL_ReadRegister TLVL_DEBUG + 20
      19              : 
      20              : #include "dtcInterfaceLib/otsStyleCoutMacros.h"
      21              : 
      22              : #undef __COUT_HDR__
      23              : #define __COUT_HDR__ "DTC " << this->getDeviceUID() << ": "
      24              : 
      25              : /// <summary>
      26              : /// Construct an instance of the DTC register map
      27              : /// </summary>
      28              : /// <param name="mode">Default: DTC_SimMode_Disabled; The simulation mode of the DTC</param>
      29              : /// <param name="dtc">DTC card index to use</param>
      30              : /// <param name="simFileName">Name to use for simulated DTC memory file, if needed</param>
      31              : /// <param name="rocMask">Nibble-mask for enabled ROCs. Ex. 0x1011 enables ROC0, 1, and 3</param>
      32              : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will
      33              : /// throw an exception if the DTC firmware does not match (Default: "")</param>
      34              : /// <param name="skipInit">Whether to skip initialization phase for reading DTC out in current state</param>
      35            0 : DTCLib::DTC_Registers::DTC_Registers(DTC_SimMode mode, int dtc, std::string simFileName, unsigned rocMask, std::string expectedDesignVersion,
      36            0 :                                                                          bool skipInit, const std::string& uid)
      37            0 :         : simMode_(mode), usingDetectorEmulator_(false), dmaSize_(64)
      38              : {
      39            0 :         TLOG(TLVL_TRACE) << "CONSTRUCTOR";
      40              : 
      41            0 :         auto sim = getenv("DTCLIB_SIM_ENABLE");
      42            0 :         if (sim != nullptr)
      43              :         {
      44            0 :                 auto simstr = std::string(sim);
      45            0 :                 simMode_ = DTC_SimModeConverter::ConvertToSimMode(simstr);
      46            0 :         }
      47              : 
      48            0 :         if (dtc == -1)
      49              :         {
      50            0 :                 auto dtcE = getenv("DTCLIB_DTC");
      51            0 :                 if (dtcE != nullptr)
      52              :                 {
      53            0 :                         dtc = atoi(dtcE);
      54              :                 }
      55              :                 else
      56            0 :                         dtc = 0;
      57              :         }
      58              : 
      59            0 :         SetSimMode(expectedDesignVersion, simMode_, dtc, simFileName, rocMask, skipInit, (uid == "" ? ("DTC" + std::to_string(dtc)) : uid));
      60            0 : }  // end constructor()
      61              : 
      62              : /// <summary>
      63              : /// DTC_Registers destructor
      64              : /// </summary>
      65            0 : DTCLib::DTC_Registers::~DTC_Registers()
      66              : {
      67            0 :         TLOG(TLVL_INFO) << "DESTRUCTOR";
      68            0 :         DisableDetectorEmulator();
      69              :         // DisableDetectorEmulatorMode();
      70              :         // DisableCFOEmulation();
      71              :         // SoftReset();
      72            0 :         TLOG(TLVL_INFO) << "DESTRUCTOR end";
      73            0 : }  // end destructor()
      74              : 
      75              : /// <summary>
      76              : /// Initialize the DTC in the given SimMode.
      77              : /// </summary>
      78              : /// <param name="expectedDesignVersion">Expected DTC Firmware Design Version. If set, will throw an exception if the DTC firmware does not match</param>
      79              : /// <param name="mode">Mode to set</param>
      80              : /// <param name="dtc">DTC card index to use</param>
      81              : /// <param name="simMemoryFile">Name to use for simulated DTC memory file, if needed</param>
      82              : /// <param name="rocMask">Default 0x1; The initially-enabled links. Each digit corresponds to a link, so all links = 0x111111</param>
      83              : /// <param name="skipInit">Whether to skip initializing the DTC using the SimMode. Used to read state.</param>
      84              : /// <returns></returns>
      85            0 : DTCLib::DTC_SimMode DTCLib::DTC_Registers::SetSimMode(std::string expectedDesignVersion, DTC_SimMode mode, int dtc, std::string simMemoryFile,
      86              :                                                                                                           unsigned rocMask, bool skipInit, const std::string& uid)
      87              : {
      88            0 :         simMode_ = mode;
      89            0 :         TLOG(TLVL_INFO) << "Initializing DTC device, sim mode is " << DTC_SimModeConverter(simMode_).toString() << " for uid = " << uid << ", deviceIndex = " << dtc << ", expectedDesignVersion = " << expectedDesignVersion;
      90              : 
      91            0 :         device_.init(simMode_, dtc, simMemoryFile, uid);
      92            0 :         if (expectedDesignVersion != "")
      93              :         {
      94            0 :                 uint32_t parsedExpectedVersion = 0;
      95            0 :                 std::string parsedDesignDate = "";
      96              :                 try
      97              :                 {
      98            0 :                         parsedExpectedVersion = static_cast<uint32_t>(std::stoul(expectedDesignVersion, nullptr, 16));
      99            0 :                         parsedDesignDate = ReadDesignDate(parsedExpectedVersion);
     100              :                 }
     101            0 :                 catch (...)  // illegal/non-hex expectedDesignVersion
     102              :                 {
     103            0 :                         __SS__;
     104            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__;
     105            0 :                         __SS_THROW__;
     106            0 :                 }
     107              : 
     108            0 :                 if (parsedExpectedVersion != ReadRegister_(CFOandDTC_Register_DesignDate))
     109              :                 {
     110            0 :                         __SS__;
     111            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__;
     112            0 :                         __SS_THROW__;
     113              :                         // throw new DTC_WrongVersionException(expectedDesignVersion, ReadDesignVersion());
     114            0 :                 }
     115            0 :         }
     116              : 
     117              :         // if (skipInit || true)
     118            0 :         if (skipInit)
     119              :         {
     120            0 :                 __COUT_INFO__ << "SKIPPING Initializing device";
     121            0 :                 return simMode_;
     122              :         }
     123              : 
     124            0 :         __COUT__ << "Initialize requested, setting device registers acccording to sim mode " << DTC_SimModeConverter(simMode_).toString();
     125              : 
     126            0 :         TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up DTC links...";
     127            0 :         for (auto link : DTC_ROC_Links)
     128              :         {
     129            0 :                 bool linkEnabled = ((rocMask >> (link * 4)) & 0x1) != 0;
     130            0 :                 if (!linkEnabled)
     131              :                 {
     132            0 :                         TLOG(TLVL_Detail) << __COUT_HDR__ << "Disabling Link " << (int)link;
     133            0 :                         DisableLink(link);
     134              : 
     135            0 :                         DisableROCEmulator(link);
     136            0 :                         SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
     137              :                 }
     138              :                 else
     139              :                 {
     140            0 :                         TLOG(TLVL_Detail) << __COUT_HDR__ << "Enabling Link " << (int)link;
     141            0 :                         EnableLink(link, DTC_LinkEnableMode(true, true));
     142              :                 }
     143              :         }
     144              : 
     145            0 :         if (simMode_ != DTC_SimMode_Disabled)
     146              :         {
     147            0 :                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation modes in Hardware...";
     148              :                 // Set up hardware simulation mode: Link 0 Tx/Rx Enabled, Loopback Enabled, ROC Emulator Enabled. All other links
     149              :                 // disabled. for (auto link : DTC_ROC_Links)
     150              :                 //      {
     151              :                 //        DisableLink(link);
     152              :                 //      }
     153              :                 //      EnableLink(DTC_Link_0, DTC_LinkEnableMode(true, true, false), DTC_ROC_0);
     154            0 :                 for (auto link : DTC_ROC_Links)
     155              :                 {
     156            0 :                         if (simMode_ == DTC_SimMode_Loopback)
     157              :                         {
     158            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of Loopback in Hardware... Link " << (int)link;
     159            0 :                                 SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_NearPCS);
     160              :                                 //                      SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
     161              :                         }
     162            0 :                         else if (simMode_ == DTC_SimMode_ROCEmulator)
     163              :                         {
     164            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Setting up simulation of ROC in Hardware... Link " << (int)link;
     165            0 :                                 EnableROCEmulator(link);
     166              :                                 // SetMaxROCNumber(DTC_Link_0, DTC_ROC_0);
     167              :                         }
     168              :                         else
     169              :                         {
     170            0 :                                 TLOG(TLVL_Detail) << __COUT_HDR__ << "Turning off simulation in Hardware... Link " << (int)link;
     171            0 :                                 SetSERDESLoopbackMode(link, DTC_SERDESLoopbackMode_Disabled);
     172            0 :                                 DisableROCEmulator(link);
     173              :                         }
     174              :                 }
     175            0 :                 SetCFOEmulationMode();
     176              :         }
     177              :         else
     178              :         {
     179            0 :                 ClearCFOEmulationMode();
     180              :         }
     181            0 :         ReadMinDMATransferLength();
     182              : 
     183            0 :         __COUT__ << "Done setting device registers";
     184            0 :         return simMode_;
     185              : }
     186              : 
     187              : /// <summary>
     188              : /// Read the DDR interface reset bit
     189              : /// </summary>
     190              : /// <returns>The current value of the DDR interface reset bit</returns>
     191            0 : bool DTCLib::DTC_Registers::ReadDDRInterfaceReset(std::optional<uint32_t> val)
     192              : {
     193            0 :         return !std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[1];
     194              : }
     195              : 
     196              : /// <summary>
     197              : /// Set the Reset bit in the Design Status register
     198              : /// </summary>
     199              : /// <param name="reset"></param>
     200            0 : void DTCLib::DTC_Registers::SetDDRInterfaceReset(bool reset)
     201              : {
     202            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_DesignStatus);
     203            0 :         data[1] = !reset;
     204            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_DesignStatus);
     205            0 : }
     206              : 
     207              : /// <summary>
     208              : /// Resets the DDR interface in the firmware
     209              : /// </summary>
     210            0 : void DTCLib::DTC_Registers::ResetDDRInterface()
     211              : {
     212            0 :         SetDDRInterfaceReset(true);
     213            0 :         usleep(1000);
     214            0 :         SetDDRInterfaceReset(false);
     215            0 :         while (ReadDDRInterfaceReset() && !ReadDDRAutoCalibrationDone())
     216              :         {
     217            0 :                 usleep(1000);
     218              :         }
     219            0 : }
     220              : 
     221              : /// <summary>
     222              : /// Read the DDR Auto Calibration Done bit of the Design status register
     223              : /// </summary>
     224              : /// <returns>Whether the DDR Auto Calibration is done</returns>
     225            0 : bool DTCLib::DTC_Registers::ReadDDRAutoCalibrationDone(std::optional<uint32_t> val)
     226              : {
     227            0 :         return std::bitset<32>(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignStatus))[0];
     228              : }
     229              : 
     230              : /// <summary>
     231              : /// Formats the register's current value for register dumps
     232              : /// </summary>
     233              : /// <returns>RegisterFormatter object containing register information</returns>
     234            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDesignStatus()
     235              : {
     236            0 :         auto form = CreateFormatter(CFOandDTC_Register_DesignStatus);
     237            0 :         form.description = "Control and Status";
     238            0 :         form.vals.push_back(std::string("Reset DDR Interface:       [") + (ReadDDRInterfaceReset(form.value) ? "x" : " ") + "]");
     239            0 :         form.vals.push_back(std::string("DDR Auto-Calibration Done: [") + (ReadDDRAutoCalibrationDone(form.value) ? "x" : " ") + "]");
     240            0 :         return form;
     241            0 : }
     242              : 
     243              : /// <summary>
     244              : /// Enable the DTC CFO Emulator
     245              : /// Parameters for the CFO Emulator, such as count and starting timestamp, must be set before enabling.
     246              : /// </summary>
     247            0 : void DTCLib::DTC_Registers::EnableCFOEmulation()
     248              : {
     249            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     250            0 :         data[30] = 1;
     251            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     252            0 : }
     253              : 
     254              : /// <summary>
     255              : /// Disable the DTC CFO Emulator
     256              : /// </summary>
     257            0 : void DTCLib::DTC_Registers::DisableCFOEmulation()
     258              : {
     259            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     260            0 :         data[30] = 0;
     261            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     262            0 : }
     263              : 
     264              : /// <summary>
     265              : /// Reads the current state of the DTC CFO Emulator
     266              : /// </summary>
     267              : /// <returns>True if the emulator is enabled, false otherwise</returns>
     268            0 : bool DTCLib::DTC_Registers::ReadCFOEmulationEnabled(std::optional<uint32_t> val)
     269              : {
     270            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     271            0 :         return dataSet[30];
     272              : }
     273              : 
     274              : /// <summary>
     275              : /// Enable CFO Loopback. CFO packets will be returned to the CFO, for delay calculation.
     276              : /// </summary>
     277            0 : void DTCLib::DTC_Registers::EnableCFOLoopback()
     278              : {
     279            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     280            0 :         data[28] = 0;  // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
     281            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     282            0 : }
     283              : 
     284              : /// <summary>
     285              : /// Disable CFO Loopback. CFO packets will be transmitted instead to the next DTC (Normal operation)
     286              : /// </summary>
     287            0 : void DTCLib::DTC_Registers::DisableCFOLoopback()
     288              : {
     289            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     290            0 :         data[28] = 1;  // 0 is for Loopback to the CFO, 1 is for propagation downstream to the next DTC in the chain
     291            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     292            0 : }
     293              : 
     294              : /// <summary>
     295              : /// Read the value of the CFO Link Loopback bit
     296              : /// </summary>
     297              : /// <returns>Value of the bit</returns>
     298            0 : bool DTCLib::DTC_Registers::ReadCFOLoopback(std::optional<uint32_t> val)
     299              : {
     300            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     301            0 :         return dataSet[28];
     302              : }
     303              : 
     304              : /// <summary>
     305              : /// Resets the DDR Write pointer to 0
     306              : /// </summary>
     307            0 : void DTCLib::DTC_Registers::ResetDDRWriteAddress()
     308              : {
     309            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     310            0 :         data[27] = 1;
     311            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     312            0 :         usleep(1000);
     313            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     314            0 :         data[27] = 0;
     315            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     316            0 : }
     317              : 
     318              : /// <summary>
     319              : /// Determine whether a DDR Write Pointer reset is in progress
     320              : /// </summary>
     321              : /// <returns>True if the DDR Write pointer is resetting, false otherwise</returns>
     322            0 : bool DTCLib::DTC_Registers::ReadResetDDRWriteAddress(std::optional<uint32_t> val)
     323              : {
     324            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     325            0 :         return data[27];
     326              : }
     327              : 
     328              : /// <summary>
     329              : /// Reset the DDR Read pointer to 0
     330              : /// </summary>
     331            0 : void DTCLib::DTC_Registers::ResetDDRReadAddress()
     332              : {
     333            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     334            0 :         data[26] = 1;
     335            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     336            0 :         usleep(1000);
     337            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     338            0 :         data[26] = 0;
     339            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     340            0 : }
     341              : 
     342              : /// <summary>
     343              : /// Determine whether the DDR Read pointer is currently being reset.
     344              : /// </summary>
     345              : /// <returns>True if the read pointer is currently being reset, false otherwise</returns>
     346            0 : bool DTCLib::DTC_Registers::ReadResetDDRReadAddress(std::optional<uint32_t> val)
     347              : {
     348            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     349            0 :         return data[26];
     350              : }
     351              : 
     352              : /// <summary>
     353              : /// Reset the DDR memory interface
     354              : /// </summary>
     355            0 : void DTCLib::DTC_Registers::ResetDDR()
     356              : {
     357            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     358            0 :         data[25] = 1;
     359            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     360            0 :         usleep(1000);
     361            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     362            0 :         data[25] = 0;
     363            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     364            0 : }
     365              : 
     366              : /// <summary>
     367              : /// Determine whether the DDR memory interface is currently being reset
     368              : /// </summary>
     369              : /// <returns>True if the DDR memory interface is currently being reset, false otherwise</returns>
     370            0 : bool DTCLib::DTC_Registers::ReadResetDDR(std::optional<uint32_t> val)
     371              : {
     372            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     373            0 :         return data[25];
     374              : }
     375              : 
     376              : /// <summary>
     377              : /// Enable sending Data Request packets from the DTC CFO Emulator with every
     378              : /// Readout Request
     379              : /// </summary>
     380            0 : void DTCLib::DTC_Registers::EnableCFOEmulatorDRP()
     381              : {
     382            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     383            0 :         data[24] = 1;
     384            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     385            0 : }
     386              : 
     387              : /// <summary>
     388              : /// Disable sending Data Request packets from the DTC CFO Emulator with every
     389              : /// Readout Request
     390              : /// </summary>
     391            0 : void DTCLib::DTC_Registers::DisableCFOEmulatorDRP()
     392              : {
     393            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     394            0 :         data[24] = 0;
     395            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     396            0 : }
     397              : 
     398              : /// <summary>
     399              : /// Read whether the DTC CFO Emulator is sending Data Request packets with every readout request
     400              : /// </summary>
     401              : /// <returns>True if the DTC CFO Emulator is sending Data Request packets with every readout request, false
     402              : /// otherwise</returns>
     403            0 : bool DTCLib::DTC_Registers::ReadCFOEmulatorDRP(std::optional<uint32_t> val)
     404              : {
     405            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     406            0 :         return data[24];
     407              : }
     408              : 
     409              : /// <summary>
     410              : /// Enable automatically generating Data Request packets when heartbeats are received
     411              : /// </summary>
     412            0 : void DTCLib::DTC_Registers::EnableAutogenDRP()
     413              : {
     414            0 :         TLOG(TLVL_AutogenDRP) << __COUT_HDR__ << "EnableAutogenDRP start";
     415            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     416            0 :         data[23] = 1;
     417            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     418            0 : }
     419              : 
     420              : /// <summary>
     421              : /// Disable automatically generating Data Request packets when heartbeats are received
     422              : /// </summary>
     423            0 : void DTCLib::DTC_Registers::DisableAutogenDRP()
     424              : {
     425            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     426            0 :         data[23] = 0;
     427            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     428            0 : }
     429              : 
     430              : /// <summary>
     431              : /// Read whether Data Request packets are generated by the DTC when heartbeats are received
     432              : /// </summary>
     433              : /// <returns>True if Data Request packets are generated by the DTC when heartbeats are received, false otherwise</returns>
     434            0 : bool DTCLib::DTC_Registers::ReadAutogenDRP(std::optional<uint32_t> val)
     435              : {
     436            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     437            0 :         return data[23];
     438              : }
     439              : 
     440              : /// <summary>
     441              : /// Enable receiving Data Request Packets from the DTCLib on DMA Channel 0
     442              : /// Possibly obsolete, ask Rick before using
     443              : /// </summary>
     444            0 : void DTCLib::DTC_Registers::EnableSoftwareDRP()
     445              : {
     446            0 :         DisableAutogenDRP();
     447            0 : }
     448              : 
     449              : /// <summary>
     450              : /// Disable receiving Data Request Packets from the DTCLib on DMA Channel 0
     451              : /// Possibly obsolete, ask Rick before using
     452              : /// </summary>
     453            0 : void DTCLib::DTC_Registers::DisableSoftwareDRP()
     454              : {
     455            0 :         EnableAutogenDRP();
     456            0 : }
     457              : //      std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     458              : //      data[22] = 0;
     459              : //      WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     460              : // }
     461              : 
     462              : /// <summary>
     463              : /// Read whether receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled
     464              : /// </summary>
     465              : /// <returns>True if receiving Data Request Packets from the DTCLib on DMA Channel 0 is enabled, false
     466              : /// otherwise</returns>
     467            0 : bool DTCLib::DTC_Registers::ReadSoftwareDRP(std::optional<uint32_t> val)
     468              : {
     469            0 :         return !ReadAutogenDRP(val);
     470              : }
     471              : 
     472              : /// <summary>
     473              : /// Enable kill of ROCs on 10x timeouts
     474              : /// </summary>
     475            0 : void DTCLib::DTC_Registers::EnableKillTimeoutROCs()
     476              : {
     477            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     478            0 :         data[22] = 1;
     479            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     480            0 : }
     481              : 
     482              : /// <summary>
     483              : /// Disable kill of ROCs on 10x timeouts
     484              : /// </summary>
     485            0 : void DTCLib::DTC_Registers::DisableKillTimeoutROCs()
     486              : {
     487            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     488            0 :         data[22] = 0;
     489            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     490            0 : }
     491              : 
     492              : /// <summary>
     493              : /// Read whether kill of ROCs on 10x timeouts is enabled
     494              : /// </summary>
     495              : /// <returns>True if kill of ROCs on 10x timeouts is enabled, false otherwise</returns>
     496            0 : bool DTCLib::DTC_Registers::ReadKillTimeoutROCs(std::optional<uint32_t> val)
     497              : {
     498            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     499            0 :         return data[22];
     500              : }
     501              : 
     502              : /// <summary>
     503              : /// Reset the PCIe interface
     504              : /// </summary>
     505            0 : void DTCLib::DTC_Registers::ResetPCIe()
     506              : {
     507            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     508              :         // data[21] = 1;  // no longer connected in firmware
     509              :         // data[20] = 1;  // no longer connected in firmware
     510            0 :         data[11] = 1;
     511            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     512            0 :         usleep(1000);
     513            0 :         data = ReadRegister_(CFOandDTC_Register_Control);
     514              :         // data[21] = 0;
     515              :         // data[20] = 0;
     516            0 :         data[11] = 0;
     517            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     518              : 
     519              :         // Note the DTC instance likely needs to be reinitialized on a firmware-DMA reset to realign pointers:
     520              :         // e.g. device_.initDMAEngine();
     521            0 : }
     522              : 
     523              : /// <summary>
     524              : /// Determine whether the PCIe interface is currently being reset
     525              : /// </summary>
     526              : /// <returns>True if the PCIe interface is currently being reset, false otherwise</returns>
     527            0 : bool DTCLib::DTC_Registers::ReadResetPCIe(std::optional<uint32_t> val)
     528              : {
     529            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     530            0 :         return data[21];
     531              : }
     532              : 
     533              : /// <summary>
     534              : /// Enable the All LED bits in Control register
     535              : /// </summary>
     536            0 : void DTCLib::DTC_Registers::EnableLEDs()
     537              : {
     538            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     539            0 :         data[16] = 1;
     540            0 :         data[17] = 1;
     541            0 :         data[18] = 1;
     542            0 :         data[19] = 1;
     543            0 :         data[20] = 1;
     544            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     545            0 : }
     546              : 
     547              : /// <summary>
     548              : /// Disable the All LED bits in Control register
     549              : /// </summary>
     550            0 : void DTCLib::DTC_Registers::DisableLEDs()
     551              : {
     552            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     553            0 :         data[16] = 0;
     554            0 :         data[17] = 0;
     555            0 :         data[18] = 0;
     556            0 :         data[19] = 0;
     557            0 :         data[20] = 0;
     558            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     559            0 : }
     560              : 
     561              : /// <summary>
     562              : /// Enable the All LED bits in Control register
     563              : /// </summary>
     564            0 : void DTCLib::DTC_Registers::FlashLEDs()
     565              : {
     566            0 :         DisableLEDs();
     567            0 :         sleep(1);
     568            0 :         EnableLEDs();
     569            0 :         sleep(1);
     570            0 :         DisableLEDs();
     571            0 : }
     572              : 
     573              : /// <summary>
     574              : /// Enable the Down LED0 Control register bit
     575              : /// </summary>
     576            0 : void DTCLib::DTC_Registers::EnableDownLED0()
     577              : {
     578            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     579            0 :         data[19] = 1;
     580            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     581            0 : }
     582              : 
     583              : /// <summary>
     584              : /// Disable the Down LED0 Control register bit
     585              : /// </summary>
     586            0 : void DTCLib::DTC_Registers::DisableDownLED0()
     587              : {
     588            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     589            0 :         data[19] = 0;
     590            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     591            0 : }
     592              : 
     593              : /// <summary>
     594              : /// Read the state of the Down LED0 Control register bit
     595              : /// </summary>
     596              : /// <returns>Whether the Down LED0 bit is set</returns>
     597            0 : bool DTCLib::DTC_Registers::ReadDownLED0State(std::optional<uint32_t> val)
     598              : {
     599            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     600            0 :         return data[19];
     601              : }
     602              : /// <summary>
     603              : /// Enable the Up LED1 Control register bit
     604              : /// </summary>
     605            0 : void DTCLib::DTC_Registers::EnableUpLED1()
     606              : {
     607            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     608            0 :         data[18] = 1;
     609            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     610            0 : }
     611              : 
     612              : /// <summary>
     613              : /// Disable the Up LED1 Control register bit
     614              : /// </summary>
     615            0 : void DTCLib::DTC_Registers::DisableUpLED1()
     616              : {
     617            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     618            0 :         data[18] = 0;
     619            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     620            0 : }
     621              : 
     622              : /// <summary>
     623              : /// Read the state of the Up LED1 Control register bit
     624              : /// </summary>
     625              : /// <returns>Whether the Up LED1 bit is set</returns>
     626            0 : bool DTCLib::DTC_Registers::ReadUpLED1State(std::optional<uint32_t> val)
     627              : {
     628            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     629            0 :         return data[18];
     630              : }
     631              : /// <summary>
     632              : /// Enable the Up LED0 Control register bit
     633              : /// </summary>
     634            0 : void DTCLib::DTC_Registers::EnableUpLED0()
     635              : {
     636            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     637            0 :         data[17] = 1;
     638            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     639            0 : }
     640              : 
     641              : /// <summary>
     642              : /// Disable the Up LED0 Control register bit
     643              : /// </summary>
     644            0 : void DTCLib::DTC_Registers::DisableUpLED0()
     645              : {
     646            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     647            0 :         data[17] = 0;
     648            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     649            0 : }
     650              : 
     651              : /// <summary>
     652              : /// Read the state of the Up LED0 Control register bit
     653              : /// </summary>
     654              : /// <returns>Whether the Up LED0 bit is set</returns>
     655            0 : bool DTCLib::DTC_Registers::ReadUpLED0State(std::optional<uint32_t> val)
     656              : {
     657            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     658            0 :         return data[17];
     659              : }
     660              : 
     661              : /// <summary>
     662              : /// Enable the LED6 Control register bit
     663              : /// </summary>
     664            0 : void DTCLib::DTC_Registers::EnableLED6()
     665              : {
     666            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     667            0 :         data[16] = 1;
     668            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     669            0 : }
     670              : 
     671              : /// <summary>
     672              : /// Disable the LED6 Control register bit
     673              : /// </summary>
     674            0 : void DTCLib::DTC_Registers::DisableLED6()
     675              : {
     676            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     677            0 :         data[16] = 0;
     678            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     679            0 : }
     680              : 
     681              : /// <summary>
     682              : /// Read the state of the LED6 Control register bit
     683              : /// </summary>
     684              : /// <returns>Whether the LED6 bit is set</returns>
     685            0 : bool DTCLib::DTC_Registers::ReadLED6State(std::optional<uint32_t> val)
     686              : {
     687            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     688            0 :         return data[16];
     689              : }
     690              : 
     691              : /// <summary>
     692              : /// Enable CFO Emulation mode.
     693              : /// </summary>
     694            0 : void DTCLib::DTC_Registers::SetCFOEmulationMode()
     695              : {
     696            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     697            0 :         data[15] = 1;
     698            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     699            0 : }
     700              : 
     701              : /// <summary>
     702              : /// Disable CFO Emulation mode.
     703              : /// </summary>
     704            0 : void DTCLib::DTC_Registers::ClearCFOEmulationMode()
     705              : {
     706            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     707            0 :         data[15] = 0;
     708            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     709            0 : }
     710              : 
     711              : /// <summary>
     712              : /// Read the state of the CFO Emulation Mode bit
     713              : /// </summary>
     714              : /// <returns>Whether CFO Emulation Mode is enabled</returns>
     715            0 : bool DTCLib::DTC_Registers::ReadCFOEmulationMode(std::optional<uint32_t> val)
     716              : {
     717            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     718            0 :         return data[15];
     719              : }
     720              : 
     721            0 : void DTCLib::DTC_Registers::SetDataFilterEnable()
     722              : {
     723            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     724            0 :         data[13] = 1;
     725            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     726            0 : }
     727              : 
     728            0 : void DTCLib::DTC_Registers::ClearDataFilterEnable()
     729              : {
     730            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     731            0 :         data[13] = 0;
     732            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     733            0 : }
     734              : 
     735            0 : bool DTCLib::DTC_Registers::ReadDataFilterEnable(std::optional<uint32_t> val)
     736              : {
     737            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     738            0 :         return data[13];
     739              : }
     740              : 
     741            0 : void DTCLib::DTC_Registers::SetDRPPrefetchEnable()
     742              : {
     743            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     744            0 :         data[12] = 1;
     745            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     746            0 : }
     747              : 
     748            0 : void DTCLib::DTC_Registers::ClearDRPPrefetchEnable()
     749              : {
     750            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     751            0 :         data[12] = 0;
     752            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     753            0 : }
     754              : 
     755            0 : bool DTCLib::DTC_Registers::ReadDRPPrefetchEnable(std::optional<uint32_t> val)
     756              : {
     757            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     758            0 :         return data[12];
     759              : }
     760              : 
     761            0 : void DTCLib::DTC_Registers::ROCInterfaceSoftReset()
     762              : {
     763            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     764            0 :         data[12] = 1;
     765            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     766            0 :         usleep(100000);
     767            0 :         data[12] = 0;
     768            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     769            0 : }
     770              : 
     771            0 : bool DTCLib::DTC_Registers::ReadROCInterfaceSoftReset(std::optional<uint32_t> val)
     772              : {
     773            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     774            0 :         return data[11];
     775              : }
     776              : 
     777            0 : void DTCLib::DTC_Registers::EnableDropDataToEmulateEventBuilding()
     778              : {
     779            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     780            0 :         data[10] = 1;
     781            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     782            0 : }
     783              : 
     784            0 : void DTCLib::DTC_Registers::DisableDropDataToEmulateEventBuilding()
     785              : {
     786            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     787            0 :         data[10] = 0;
     788            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     789            0 : }
     790              : 
     791            0 : bool DTCLib::DTC_Registers::ReadDropDataToEmulateEventBuilding(std::optional<uint32_t> val)
     792              : {
     793            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     794            0 :         return data[10];
     795              : }
     796              : 
     797              : /// This offset should be set 'permanently' for the DTC in response to
     798              : ///             the sample measurement at bits [18:16] of DTC_Register_CFOLinkErrorFlags
     799            0 : void DTCLib::DTC_Registers::SetCFOSamplePermanentOffset(int permanentOffset)
     800              : {
     801              :         // do not write more bits because high bits, in older versions were the error clear latch... ReadRegister_(DTC_Register_CFOLinkErrorFlags);
     802              :         // set only 3-bits [2:0]
     803            0 :         WriteRegister_(permanentOffset & 7, DTC_Register_CFOLinkErrorFlags);
     804            0 : }  // end SetCFOSamplePermanentOffset()
     805              : 
     806            0 : int DTCLib::DTC_Registers::ReadCFOSamplePermanentOffset(std::optional<uint32_t> val)
     807              : {
     808            0 :         uint32_t setting = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
     809            0 :         setting &= 7;
     810            0 :         if (setting > 3)
     811            0 :                 setting = -8 + setting;
     812            0 :         return setting;  // return 3-bit value handling of [-2,2]
     813              : }  // end ReadCFOSamplePermanentOffset()
     814              : 
     815              : /// @brief Set edge selection of RTF clock and external CFO rx -> tx data
     816              : /// @param forceCFOedge is a 2-bit value
     817            0 : void DTCLib::DTC_Registers::SetExternalCFOSampleEdgeMode(int forceCFOedge)
     818              : {
     819            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     820              : 
     821            0 :         data[6] = ((forceCFOedge >> 1) & 1) ? 0 : 1;  // invert bit[1], DTC control bit [6] := 1 for forced, 0 for auto
     822            0 :         data[5] = (forceCFOedge & 1);                 // DTC control bit [5] := 1 for falling-edge, 0 for rising-edge
     823            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     824            0 : }  // end SetExternalCFOSampleEdgeMode()
     825              : 
     826            0 : int DTCLib::DTC_Registers::ReadExternalCFOSampleEdgeMode(std::optional<uint32_t> val)
     827              : {
     828            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     829            0 :         return (data[6] << 1) | data[5];
     830              : }  // end ReadExternalCFOSampleEdgeMode()
     831              : 
     832              : /// @brief Toggle only the CFO sample clock edge (Control Register bit 5), leaving the
     833              : ///        forced/auto select (bit 6) untouched.
     834              : /// @return the new edge bit value: 0 = rising-edge (posedge), 1 = falling-edge (negedge)
     835            0 : int DTCLib::DTC_Registers::ToggleExternalCFOSampleEdge()
     836              : {
     837            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     838            0 :         data[5] = !data[5];  // DTC control bit [5]: 1 for falling-edge, 0 for rising-edge
     839            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     840            0 :         return data[5];
     841              : }  // end ToggleExternalCFOSampleEdge()
     842              : 
     843            0 : void DTCLib::DTC_Registers::SetRTFPunchedClockEdge(bool posedge)
     844              : {
     845            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     846            0 :         data[7] = posedge ? 1 : 0;
     847            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     848            0 : }
     849              : 
     850            0 : bool DTCLib::DTC_Registers::ReadRTFPunchedClockEdge(std::optional<uint32_t> val)
     851              : {
     852            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     853            0 :         return data[7];
     854              : }
     855              : 
     856              : /// @return the new edge bit value: 0 = negedge, 1 = posedge
     857            0 : int DTCLib::DTC_Registers::ToggleRTFPunchedClockEdge()
     858              : {
     859            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     860            0 :         data[7] = !data[7];
     861            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     862            0 :         return data[7];
     863              : }
     864              : 
     865            0 : void DTCLib::DTC_Registers::SetExternalFanoutClockInput()
     866              : {
     867            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     868            0 :         data[4] = 1;
     869            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     870            0 : }
     871              : 
     872            0 : void DTCLib::DTC_Registers::SetInternalFanoutClockInput()
     873              : {
     874            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     875            0 :         data[4] = 0;
     876            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     877            0 : }
     878              : 
     879            0 : bool DTCLib::DTC_Registers::ReadFanoutClockInput(std::optional<uint32_t> val)
     880              : {
     881            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     882            0 :         return data[4];
     883              : }
     884              : 
     885              : /// <summary>
     886              : /// Enable receiving DCS packets.
     887              : /// </summary>
     888            0 : void DTCLib::DTC_Registers::EnableDCSReception()
     889              : {
     890            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     891            0 :         data[2] = 1;
     892            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     893            0 : }
     894              : /// <summary>
     895              : /// Disable receiving DCS packets. Any DCS packets received will be ignored
     896              : /// </summary>
     897            0 : void DTCLib::DTC_Registers::DisableDCSReception()
     898              : {
     899            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_Control);
     900            0 :         data[2] = 0;
     901            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_Control);
     902            0 : }
     903              : /// <summary>
     904              : /// Read the status of the DCS Enable bit
     905              : /// </summary>
     906              : /// <returns>Whether DCS packet reception is enabled</returns>
     907            0 : bool DTCLib::DTC_Registers::ReadDCSReception(std::optional<uint32_t> val)
     908              : {
     909            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_Control);
     910            0 :         return data[2];
     911              : }
     912              : 
     913              : /// <summary>
     914              : /// Formats the register's current value for register dumps
     915              : /// </summary>
     916              : /// <returns>RegisterFormatter object containing register information</returns>
     917            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDTCControl()
     918              : {
     919            0 :         auto form = CreateFormatter(CFOandDTC_Register_Control);
     920            0 :         form.description = "DTC Control";
     921            0 :         form.vals.push_back("([ x = 1 (hi) ])");
     922              : 
     923              :         // ~~~  DTC Control Register (0x9100) ~~~
     924              :         // Bit Position Mode    Default Value   Description
     925              :         // 31   WO      0b0     DTC Soft Reset (Self-clearing)
     926              :         // 30   RW      0b0     CFO Emulation Enable
     927              :         // 29   RW      0b0     Reserved (Formerly CFO Emulation Enable Continuous)
     928              :         // 28   RW      0b0     CFO Link Output Control
     929              :         // 27   RW      0b0     Reset DDR Write Address
     930              :         // 26   RW      0b0     Reserved (Formerly Reset DDR Read Address)
     931              :         // 25   RW      0b0     Reserved (DDR Interface Reset)
     932              :         // 24   RW      0b0     CFO Emulator DRP Enable
     933              :         // 23   RW      0b0     DTC Autogenerate DRP Enable
     934              :         // 22   RW      0b0     Reserved (Formerly Software DRP Enable)
     935              :         // 21   RW      0b0     Reserved (Formerly local EVB Source Buffer Reset)
     936              :         // 20   RW      0b0     Reserved (Formerly EVB DMA Buffer Reset)
     937              :         // 19   RW      0b0     Down LED 0
     938              :         // 18   RW      0b0     Up LED 1
     939              :         // 17   RW      0b0     Up LED 0
     940              :         // 16   RW      0b0     LED 7
     941              :         // 15   RW      0b0     CFO Emulation Mode
     942              :         // 14   RW      0b0     Reserved (Formerly EVB Debug Count Enable)
     943              :         // 13   RW      0b0     Reserved (Formerly Trigger Filter Enable)
     944              :         // 12   RW      0b0     DRP Prefetch Enable
     945              :         // 11   RW      0b0     Reserved (Formerly EVM Buffer Reset)
     946              :         // 10   RW      0b0     Drop Subevent Data to Emulate Hardware Event Building Reserved (Formerly Sequence Number Disable)
     947              :         // 9    RW      0b0     Punch Enable on RJ-45 Output
     948              :         // 8    RW      0b0     SERDES Global Reset
     949              :         // 7    RW      0b0     RTF Punched Clock Edge Select (0=negedge, 1=posedge)
     950              :         // 6    RW      0b0     Do Force External CFO Sample Edge (Formerly RX Packet Error Feedback Enable)
     951              :         // 5    RW      0b0     Force External CFO Sample Edge Select (Formerly Comma Tolerance Enable)
     952              :         // 4    RW      0b0     Fanout Clock Input Select
     953              :         // 3    RW      0b0     CFO Emulator Loopback Test Launch Control
     954              :         // 2    RW      0b0     DCS Enable
     955              :         // 1    RW      0b0     Reserved (Formerly SERDES Comma Align)
     956              :         // 0    WO      0b0     DTC Hard Reset (Self-clearing)
     957              : 
     958            0 :         form.vals.push_back(std::string("Bit-31 DTC Soft Reset (Self-clearing):       [") + (ReadSoftReset(form.value) ? "x" : " ") + "]");
     959            0 :         form.vals.push_back(std::string("Bit-30 CFO Emulation Enable:                 [") + (ReadCFOEmulationEnabled(form.value) ? "x" : " ") + "]");
     960            0 :         form.vals.push_back(std::string("Bit-28 CFO Link Timing Card not-in-Loopback: [") + (ReadCFOLoopback(form.value) ? "x" : " ") + "]");
     961              :         // form.vals.push_back(std::string("Bit-27 Reset DDR Write Address:         [") + (ReadResetDDRWriteAddress(form.value) ? "x" : " ") + "]");
     962              :         // form.vals.push_back(std::string("Bit-26 Reset DDR Read Address:          [") + (ReadResetDDRReadAddress(form.value) ? "x" : " ") + "]");
     963              :         // form.vals.push_back(std::string("Bit-25 Reset DDR Interface:             [") + (ReadResetDDR(form.value) ? "x" : " ") + "]");
     964              :         // form.vals.push_back(std::string("Bit-24 CFO Emulator DRP Enable:         [") + (ReadCFOEmulatorDRP(form.value) ? "x" : " ") + "]");
     965            0 :         form.vals.push_back(std::string("Bit-23 DTC Autogenerate DRP:                 [") + (ReadAutogenDRP(form.value) ? "x" : " ") + "]");
     966              :         // Bit-22 is currently defined as "Kill ROCs on 10x Timeouts" (legacy Software DRP meaning no longer applies).
     967            0 :         form.vals.push_back(std::string("Bit-22 Kill ROCs on 10x Timeouts:            [") + (ReadKillTimeoutROCs(form.value) ? "x" : " ") + "]");
     968            0 :         form.vals.push_back(std::string("Bit-19 Down LED 0:                           [") + (ReadDownLED0State(form.value) ? "x" : " ") + "]");
     969            0 :         form.vals.push_back(std::string("Bit-18 Up LED 1:                             [") + (ReadUpLED1State(form.value) ? "x" : " ") + "]");
     970            0 :         form.vals.push_back(std::string("Bit-17 Up LED 0:                             [") + (ReadUpLED0State(form.value) ? "x" : " ") + "]");
     971            0 :         form.vals.push_back(std::string("Bit-16 LED 6:                                [") + (ReadLED6State(form.value) ? "x" : " ") + "]");
     972            0 :         form.vals.push_back(std::string("Bit-15 CFO Emulation Mode:                   [") + (ReadCFOEmulationMode(form.value) ? "x" : " ") + "]");
     973              :         // form.vals.push_back(std::string("Bit-31 Data Filter Enable:              [") + (ReadDataFilterEnable(form.value) ? "x" : " ") + "]");
     974            0 :         form.vals.push_back(std::string("Bit-12 DRP Prefetch Enable:                  [") + (ReadDRPPrefetchEnable(form.value) ? "x" : " ") + "]");
     975            0 :         form.vals.push_back(std::string("Bit-10 Skip-by-32 Subevent Readout Enable:   [") + (ReadDropDataToEmulateEventBuilding(form.value) ? "x" : " ") + "]");
     976              :         // form.vals.push_back(std::string("Bit-31 ROC Interface Soft Reset:        [") + (ReadROCInterfaceSoftReset(form.value) ? "x" : " ") + "]");
     977              :         // form.vals.push_back(std::string("Bit-31 Sequence Number Disable:         [") + (ReadSequenceNumberDisable(form.value) ? "x" : " ") + "]");
     978              :         // form.vals.push_back(std::string("Bit-31 Punch Enable:                    [") + (ReadPunchEnable(form.value) ? "x" : " ") + "]");
     979              : 
     980            0 :         form.vals.push_back(std::string("Bit-09 Punched Clock Enable:                 [") + (CFOandDTC_Registers::ReadPunchEnable(form.value) ? "x" : " ") + "]");
     981            0 :         form.vals.push_back(std::string("Bit-08 SERDES Global Reset:                  [") + (CFOandDTC_Registers::ReadResetSERDES(form.value) ? "x" : " ") + "]");
     982            0 :         form.vals.push_back(std::string("Bit-07 RTF Punched Clock Edge Select:        [") + (ReadRTFPunchedClockEdge(form.value) ? "posedge" : "negedge") + "]");
     983              : 
     984            0 :         form.vals.push_back(std::string("Bit-06 Enable CFO-RTF Offset Control:        [") + (((ReadExternalCFOSampleEdgeMode(form.value) >> 1) & 1) ? "x" : " ") + "]");
     985            0 :         form.vals.push_back(std::string("Bit-05 CFO-RTF Edge Select:                  [") + ((ReadExternalCFOSampleEdgeMode(form.value) & 1) ? "negedge" : "posedge") + "]");
     986              : 
     987              :         // form.vals.push_back(std::string("Bit-31 RX Packet Error Feedback Enable: [") + (ReadRxPacketErrorFeedbackEnable(form.value) ? "x" : " ") + "]");
     988              :         // form.vals.push_back(std::string("Bit-31 Comma Tolerance Enable:          [") + (ReadCommaToleranceEnable(form.value) ? "x" : " ") + "]");
     989            0 :         form.vals.push_back(std::string("Bit-04 Fanout Clock Input Select:            [") + (ReadFanoutClockInput(form.value) ? "FMC SFP Rx" : "FPGA") + "]");
     990            0 :         form.vals.push_back(std::string("Bit-02 DCS Enable:                           [") + (ReadDCSReception(form.value) ? "x" : " ") + "]");
     991            0 :         form.vals.push_back(std::string("Bit-00 DTC Hard Reset (Self-clearing):       [") + (ReadHardReset(form.value) ? "x" : " ") + "]");
     992            0 :         return form;
     993            0 : }
     994              : 
     995              : // DMA Transfer Length Register
     996              : /// <summary>
     997              : /// Set the DMA buffer size which will automatically trigger a DMA
     998              : /// </summary>
     999              : /// <param name="length">Size, in bytes of buffer that will trigger a DMA</param>
    1000            0 : void DTCLib::DTC_Registers::SetTriggerDMATransferLength(uint16_t length)
    1001              : {
    1002            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1003            0 :         data = (data & 0x0000FFFF) + (length << 16);
    1004            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
    1005            0 : }
    1006              : 
    1007              : /// <summary>
    1008              : /// Read the DMA buffer size which will automatically trigger a DMA
    1009              : /// </summary>
    1010              : /// <returns>The DMA buffer size which will automatically trigger a DMA, in bytes</returns>
    1011            0 : uint16_t DTCLib::DTC_Registers::ReadTriggerDMATransferLength(std::optional<uint32_t> val)
    1012              : {
    1013            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1014            0 :         data >>= 16;
    1015            0 :         return static_cast<uint16_t>(data);
    1016              : }
    1017              : 
    1018              : /// <summary>
    1019              : /// Set the minimum DMA transfer size. Absolute minimum is 64 bytes.
    1020              : /// Buffers smaller than this size will be padded to the minimum.
    1021              : /// </summary>
    1022              : /// <param name="length">Size, in bytes, of the minimum DMA transfer buffer</param>
    1023            0 : void DTCLib::DTC_Registers::SetMinDMATransferLength(uint16_t length)
    1024              : {
    1025            0 :         auto data = ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1026            0 :         data = (data & 0xFFFF0000) + length;
    1027            0 :         WriteRegister_(data, CFOandDTC_Register_DMATransferLength);
    1028            0 : }
    1029              : 
    1030              : /// <summary>
    1031              : /// Read the minimum DMA transfer size.
    1032              : /// </summary>
    1033              : /// <returns>The minimum DMA size, in bytes</returns>
    1034            0 : uint16_t DTCLib::DTC_Registers::ReadMinDMATransferLength(std::optional<uint32_t> val)
    1035              : {
    1036            0 :         auto data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DMATransferLength);
    1037            0 :         data = data & 0x0000FFFF;
    1038            0 :         dmaSize_ = static_cast<uint16_t>(data);
    1039            0 :         return dmaSize_;
    1040              : }
    1041              : 
    1042              : /// <summary>
    1043              : /// Formats the register's current value for register dumps
    1044              : /// </summary>
    1045              : /// <returns>RegisterFormatter object containing register information</returns>
    1046            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATransferLength()
    1047              : {
    1048            0 :         auto form = CreateFormatter(CFOandDTC_Register_DMATransferLength);
    1049            0 :         form.description = "DMA Transfer Length";
    1050            0 :         std::stringstream o;
    1051            0 :         o << "Trigger Length: 0x" << std::hex << ReadTriggerDMATransferLength(form.value);
    1052            0 :         form.vals.push_back(o.str());
    1053            0 :         std::stringstream p;
    1054            0 :         p << "Minimum Length: 0x" << std::hex << ReadMinDMATransferLength(form.value);
    1055            0 :         form.vals.push_back(p.str());
    1056            0 :         return form;
    1057            0 : }
    1058              : 
    1059              : // SERDES Loopback Enable Register
    1060              : /// <summary>
    1061              : /// Set the SERDES Loopback mode for the given link
    1062              : /// </summary>
    1063              : /// <param name="link">Link to set for</param>
    1064              : /// <param name="mode">DTC_SERDESLoopbackMode to set</param>
    1065            0 : void DTCLib::DTC_Registers::SetSERDESLoopbackMode(DTC_Link_ID const& link, const DTC_SERDESLoopbackMode& mode)
    1066              : {
    1067            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable);
    1068            0 :         std::bitset<3> modeSet = mode;
    1069            0 :         data[3 * link] = modeSet[0];
    1070            0 :         data[3 * link + 1] = modeSet[1];
    1071            0 :         data[3 * link + 2] = modeSet[2];
    1072            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_LoopbackEnable);
    1073            0 : }
    1074              : 
    1075              : /// <summary>
    1076              : /// Read the SERDES Loopback mode for the given link
    1077              : /// </summary>
    1078              : /// <param name="link">Link to read</param>
    1079              : /// <returns>DTC_SERDESLoopbackMode of the link</returns>
    1080            0 : DTCLib::DTC_SERDESLoopbackMode DTCLib::DTC_Registers::ReadSERDESLoopback(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1081              : {
    1082            0 :         std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_LoopbackEnable)) >> 3 * link;
    1083            0 :         return static_cast<DTC_SERDESLoopbackMode>(dataSet.to_ulong());
    1084              : }
    1085              : 
    1086              : /// <summary>
    1087              : /// Formats the register's current value for register dumps
    1088              : /// </summary>
    1089              : /// <returns>RegisterFormatter object containing register information</returns>
    1090            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESLoopbackEnable()
    1091              : {
    1092            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
    1093            0 :         form.description = "SERDES Loopback Enable";
    1094            0 :         form.vals.push_back("");  // translation
    1095            0 :         for (auto r : DTC_ROC_Links)
    1096              :         {
    1097            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " +
    1098            0 :                                                         DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(r, form.value)).toString());
    1099              :         }
    1100            0 :         form.vals.push_back(std::string("CFO:    ") +
    1101            0 :                                                 DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_CFO, form.value)).toString());
    1102            0 :         form.vals.push_back(std::string("EVB:    ") +
    1103            0 :                                                 DTC_SERDESLoopbackModeConverter(ReadSERDESLoopback(DTC_Link_EVB, form.value)).toString());
    1104            0 :         return form;
    1105            0 : }
    1106              : 
    1107              : // Clock Status Register
    1108              : /// <summary>
    1109              : /// Read the SERDES Oscillator IIC Error Bit
    1110              : /// </summary>
    1111              : /// <returns>True if the SERDES Oscillator IIC Error is set</returns>
    1112            0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICError(std::optional<uint32_t> val)
    1113              : {
    1114            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
    1115            0 :         return dataSet[2];
    1116              : }
    1117              : 
    1118              : /// <summary>
    1119              : /// Read the DDR Oscillator IIC Error Bit
    1120              : /// </summary>
    1121              : /// <returns>True if the DDR Oscillator IIC Error is set</returns>
    1122            0 : bool DTCLib::DTC_Registers::ReadDDROscillatorIICError(std::optional<uint32_t> val)
    1123              : {
    1124            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_ClockOscillatorStatus);
    1125            0 :         return dataSet[18];
    1126              : }
    1127              : 
    1128              : /// <summary>
    1129              : /// Formats the register's current value for register dumps
    1130              : /// </summary>
    1131              : /// <returns>RegisterFormatter object containing register information</returns>
    1132            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatClockOscillatorStatus()
    1133              : {
    1134            0 :         auto form = CreateFormatter(CFOandDTC_Register_ClockOscillatorStatus);
    1135            0 :         form.description = "Clock Oscillator Status";
    1136            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1137            0 :         form.vals.push_back(std::string("SERDES IIC Error:     [") + (ReadSERDESOscillatorIICError(form.value) ? "x" : " ") + "]");
    1138            0 :         form.vals.push_back(std::string("DDR IIC Error:        [") + (ReadDDROscillatorIICError(form.value) ? "x" : " ") + "]");
    1139            0 :         return form;
    1140            0 : }
    1141              : 
    1142              : // ROC Emulation Enable Register
    1143              : /// <summary>
    1144              : /// Enable the ROC emulator on the given link
    1145              : /// </summary>
    1146              : /// <param name="link">Link to enable</param>
    1147            0 : void DTCLib::DTC_Registers::EnableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
    1148              : {
    1149            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
    1150            0 :         if (link == DTC_Link_ALL)
    1151            0 :                 for (const auto& l : DTC_ROC_Links)
    1152            0 :                         dataSet[l + type * 6] = 1;
    1153              :         else
    1154            0 :                 dataSet[link + type * 6] = 1;
    1155              : 
    1156            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
    1157            0 : }
    1158              : 
    1159              : /// <summary>
    1160              : /// Disable the ROC emulator on the given link
    1161              : /// </summary>
    1162              : /// <param name="link">Link to disable</param>
    1163            0 : void DTCLib::DTC_Registers::DisableROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type)
    1164              : {
    1165            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_ROCEmulationEnable);
    1166            0 :         if (link == DTC_Link_ALL)
    1167            0 :                 for (const auto& l : DTC_ROC_Links)
    1168            0 :                         dataSet[l + type * 6] = 0;
    1169              :         else
    1170            0 :                 dataSet[link + type * 6] = 0;
    1171              : 
    1172            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_ROCEmulationEnable);
    1173            0 : }
    1174              : 
    1175              : /// <summary>
    1176              : /// Read the state of the ROC emulator on the given link
    1177              : /// </summary>
    1178              : /// <param name="link">Link to read</param>
    1179              : /// <returns>True if the ROC Emulator is enabled on the link</returns>
    1180            0 : bool DTCLib::DTC_Registers::ReadROCEmulator(DTC_Link_ID const& link, DTC_ROC_Emulation_Type const& type, std::optional<uint32_t> val)
    1181              : {
    1182            0 :         if (std::find(DTC_ROC_Links.begin(), DTC_ROC_Links.end(), link) == DTC_ROC_Links.end())
    1183              :         {
    1184            0 :                 __SS__ << "Illegal link specified for ROC Emulator target: " << link << __E__;
    1185            0 :                 __SS_THROW__;
    1186            0 :         }
    1187              : 
    1188            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
    1189            0 :         return dataSet[link + type * 6];
    1190              : }
    1191            0 : void DTCLib::DTC_Registers::SetROCEmulatorMask(uint32_t rocEnableMask)
    1192              : {
    1193            0 :         WriteRegister_(rocEnableMask, DTC_Register_ROCEmulationEnable);
    1194            0 : }
    1195            0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorMask(std::optional<uint32_t> val)
    1196              : {
    1197            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCEmulationEnable);
    1198              : }
    1199              : 
    1200              : /// <summary>
    1201              : /// Formats the register's current value for register dumps
    1202              : /// </summary>
    1203              : /// <returns>RegisterFormatter object containing register information</returns>
    1204            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationEnable()
    1205              : {
    1206            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulationEnable);
    1207            0 :         form.description = "ROC Emulator Enable";
    1208            0 :         form.vals.push_back("       ([ Internal, Fiber-Loopback, External ])");  // translation
    1209            0 :         for (auto r : DTC_ROC_Links)
    1210            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) +
    1211            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" : ".") + "]");
    1212              : 
    1213            0 :         return form;
    1214            0 : }
    1215              : 
    1216              : // Link Enable Register
    1217              : /// <summary>
    1218              : /// Enable Receive CFO Link
    1219              : /// </summary>
    1220            0 : void DTCLib::DTC_Registers::EnableReceiveCFOLink()
    1221              : {
    1222            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1223            0 :         data[14] = 1;
    1224            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1225            0 : }
    1226              : /// <summary>
    1227              : /// Disable Receive CFO Link
    1228              : /// </summary>
    1229            0 : void DTCLib::DTC_Registers::DisableReceiveCFOLink()
    1230              : {
    1231            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1232            0 :         data[14] = 0;
    1233            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1234            0 : }
    1235              : /// <summary>
    1236              : /// Enable Receive CFO Link
    1237              : /// </summary>
    1238            0 : void DTCLib::DTC_Registers::EnableTransmitCFOLink()
    1239              : {
    1240            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1241            0 :         data[6] = 1;
    1242            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1243            0 : }
    1244              : /// <summary>
    1245              : /// Disable Receive CFO Link
    1246              : /// </summary>
    1247            0 : void DTCLib::DTC_Registers::DisableTransmitCFOLink()
    1248              : {
    1249            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1250            0 :         data[6] = 0;
    1251            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1252            0 : }
    1253              : /// <summary>
    1254              : /// Enable a SERDES Link based on the mode tx/rx enable bits (default is enabled)
    1255              : /// </summary>
    1256              : /// <param name="link">Link to enable</param>
    1257              : /// <param name="mode">Link enable bits to set (Default: All)</param>
    1258            0 : void DTCLib::DTC_Registers::EnableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
    1259              : {
    1260            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1261            0 :         data[link] = mode.TransmitEnable;
    1262            0 :         data[link + 8] = mode.ReceiveEnable;
    1263            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1264            0 : }
    1265              : 
    1266              : /// <summary>
    1267              : /// Disable a SERDES Link
    1268              : /// The given mode bits will be UNSET
    1269              : /// </summary>
    1270              : /// <param name="link">Link to disable</param>
    1271              : /// <param name="mode">Link enable bits to unset (Default: All)</param>
    1272            0 : void DTCLib::DTC_Registers::DisableLink(DTC_Link_ID const& link, const DTC_LinkEnableMode& mode)
    1273              : {
    1274            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1275            0 :         data[link] = data[link] && !mode.TransmitEnable;
    1276            0 :         data[link + 8] = data[link + 8] && !mode.ReceiveEnable;
    1277            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1278            0 : }
    1279              : 
    1280              : /// <summary>
    1281              : /// Read the Link Enable bits for a given SERDES link
    1282              : /// </summary>
    1283              : /// <param name="link">Link to read</param>
    1284              : /// <returns>DTC_LinkEnableMode containing TX, RX, and CFO bits</returns>
    1285            0 : DTCLib::DTC_LinkEnableMode DTCLib::DTC_Registers::ReadLinkEnabled(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1286              : {
    1287            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1288            0 :         return DTC_LinkEnableMode(dataSet[link], dataSet[link + 8]);
    1289              : }
    1290            0 : uint32_t DTCLib::DTC_Registers::ReadLinkEnabledData()
    1291              : {
    1292            0 :         return ReadRegister_(CFOandDTC_Register_LinkEnable);
    1293              : }
    1294              : 
    1295            0 : bool DTCLib::DTC_Registers::ReadBlockNullHeartbeatsToROC(std::optional<uint32_t> val)
    1296              : {
    1297            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1298            0 :         return dataSet[24];
    1299              : }
    1300            0 : void DTCLib::DTC_Registers::SetBlockNullHeartbeatsToROC(bool enable)
    1301              : {
    1302            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1303            0 :         data[24] = enable;
    1304            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1305            0 : }
    1306              : 
    1307            0 : bool DTCLib::DTC_Registers::ReadResequenceNonNullEvents(std::optional<uint32_t> val)
    1308              : {
    1309            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1310            0 :         return dataSet[25];
    1311              : }
    1312            0 : void DTCLib::DTC_Registers::SetResequenceNonNullEvents(bool enable)
    1313              : {
    1314            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1315            0 :         data[25] = enable;
    1316            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1317            0 : }
    1318              : 
    1319            0 : bool DTCLib::DTC_Registers::ReadAutoGenDRPPerLink(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1320              : {
    1321            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_LinkEnable);
    1322            0 :         return dataSet[link + 16];
    1323              : }
    1324            0 : void DTCLib::DTC_Registers::SetAutoGenDRPPerLink(DTC_Link_ID const& link, bool enable)
    1325              : {
    1326            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_LinkEnable);
    1327            0 :         data[link + 16] = enable;
    1328            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_LinkEnable);
    1329            0 : }
    1330              : 
    1331              : /// <summary>
    1332              : /// Formats the register's current value for register dumps
    1333              : /// </summary>
    1334              : /// <returns>RegisterFormatter object containing register information</returns>
    1335            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkEnable()
    1336              : {
    1337            0 :         auto form = CreateFormatter(CFOandDTC_Register_LinkEnable);
    1338            0 :         form.description = "Link Enable";
    1339            0 :         form.vals.push_back("       ([TX, RX])");
    1340            0 :         for (auto r : DTC_ROC_Links)
    1341              :         {
    1342            0 :                 auto re = ReadLinkEnabled(r, form.value);
    1343            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.TransmitEnable ? "x" : ".") + "" +
    1344            0 :                                                         (re.ReceiveEnable ? "x" : ".") + "]");
    1345              :         }
    1346              :         {
    1347            0 :                 auto ce = ReadLinkEnabled(DTC_Link_CFO, form.value);
    1348            0 :                 form.vals.push_back(std::string("CFO:    [") + (ce.TransmitEnable ? "x" : ".") + "" +
    1349            0 :                                                         (ce.ReceiveEnable ? "x" : ".") + "]");
    1350              :         }
    1351              :         {
    1352            0 :                 auto ee = ReadLinkEnabled(DTC_Link_EVB, form.value);
    1353            0 :                 form.vals.push_back(std::string("EVB:    [") + (ee.TransmitEnable ? "x" : ".") + "" +
    1354            0 :                                                         (ee.ReceiveEnable ? "x" : ".") + "]");
    1355              :         }
    1356            0 :         form.vals.push_back(std::string("Block Null Heartbeats to ALL ROCs: [") +
    1357            0 :                                                 (ReadBlockNullHeartbeatsToROC(form.value) ? "x" : ".") + "]");
    1358            0 :         form.vals.push_back(std::string("Resequence Non-null Events for ALL ROCs:   [") +
    1359            0 :                                                 (ReadResequenceNonNullEvents(form.value) ? "x" : ".") + "]");
    1360            0 :         for (auto r : DTC_ROC_Links)
    1361              :         {
    1362            0 :                 form.vals.push_back(std::string("Auto-Gen DRP Link ") + std::to_string(r) + ": [" +
    1363            0 :                                                         (ReadAutoGenDRPPerLink(r, form.value) ? "x" : ".") + "]");
    1364              :         }
    1365            0 :         return form;
    1366            0 : }
    1367              : 
    1368              : // SERDES Reset Register
    1369              : /// <summary>
    1370              : /// Reset the SERDES TX side
    1371              : /// Will poll the Reset SERDES TX Done flag until the SERDES reset is complete
    1372              : /// </summary>
    1373              : /// <param name="link">Link to reset</param>
    1374              : /// <param name="interval">Polling interval, in microseconds</param>
    1375            0 : void DTCLib::DTC_Registers::ResetSERDESTX(DTC_Link_ID const& link, int interval)
    1376              : {
    1377            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES TX Reset Loop for Link " << link;
    1378            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1379            0 :         if (link == DTC_Link_ALL)
    1380              :         {
    1381            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1382            0 :                         data[i + 24] = 1;
    1383              :         }
    1384              :         else
    1385            0 :                 data[link + 24] = 1;
    1386            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1387              : 
    1388            0 :         usleep(interval);
    1389              : 
    1390            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1391            0 :         if (link == DTC_Link_ALL)
    1392              :         {
    1393            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1394            0 :                         data[i + 24] = 0;
    1395              :         }
    1396              :         else
    1397            0 :                 data[link + 24] = 0;
    1398            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1399              : 
    1400            0 :         auto resetDone = false;
    1401            0 :         uint32_t loops = 0;
    1402            0 :         while (!resetDone && ++loops < 10)
    1403              :         {
    1404            0 :                 usleep(interval);
    1405              : 
    1406              :                 // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
    1407            0 :                 resetDone = true;
    1408              :                 // if(link == DTC_Link_ALL)
    1409              :                 // {
    1410              :                 //      //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1411              :                 //      resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
    1412              :                 // }
    1413              :                 // else
    1414              :                 //      resetDone = ReadResetTXSERDESDone(link);
    1415              : 
    1416            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES TX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1417              :         }
    1418              : 
    1419            0 :         if (loops >= 10)
    1420              :         {
    1421            0 :                 __SS__ << "Timeout waiting for SERDES TX Reset loop.";
    1422            0 :                 __SS_THROW__;
    1423              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES TX Reset loop.");
    1424            0 :         }
    1425            0 : }
    1426              : 
    1427              : /// <summary>
    1428              : /// Read if a SERDES TX reset is currently in progress
    1429              : /// </summary>
    1430              : /// <param name="link">Link to read</param>
    1431              : /// <returns>True if a SERDES TX reset is in progress</returns>
    1432            0 : bool DTCLib::DTC_Registers::ReadResetSERDESTX(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1433              : {
    1434            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1435            0 :         return dataSet[link + 24];
    1436              : }
    1437              : 
    1438              : /// <summary>
    1439              : /// Reset the SERDES RX side
    1440              : /// Will poll the Reset SERDES RX Done flag until the SERDES reset is complete
    1441              : /// </summary>
    1442              : /// <param name="link">Link to reset</param>
    1443              : /// <param name="interval">Polling interval, in microseconds</param>
    1444            0 : void DTCLib::DTC_Registers::ResetSERDESRX(DTC_Link_ID const& link, int interval)
    1445              : {
    1446            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES RX Reset Loop for Link " << link;
    1447            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1448            0 :         if (link == DTC_Link_ALL)
    1449              :         {
    1450            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1451            0 :                         data[i + 16] = 1;
    1452              :         }
    1453              :         else
    1454            0 :                 data[link + 16] = 1;
    1455            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1456              : 
    1457            0 :         usleep(interval);
    1458              : 
    1459            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1460            0 :         if (link == DTC_Link_ALL)
    1461              :         {
    1462            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1463            0 :                         data[i + 16] = 0;
    1464              :         }
    1465              :         else
    1466            0 :                 data[link + 16] = 0;
    1467            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1468              : 
    1469            0 :         auto resetDone = false;
    1470            0 :         uint32_t loops = 0;
    1471            0 :         while (!resetDone && ++loops < 10)
    1472              :         {
    1473            0 :                 usleep(interval);
    1474              : 
    1475              :                 // DO NOT CHECK until bit 7-0 resets, that seems to update all reset done bits
    1476            0 :                 resetDone = true;
    1477              :                 // if(link == DTC_Link_ALL)
    1478              :                 // {
    1479              :                 //      //Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1480              :                 //      resetDone = ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF;
    1481              :                 // }
    1482              :                 // else
    1483              :                 //      resetDone = ReadResetRXSERDESDone(link);
    1484              : 
    1485            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES RX Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1486              :         }
    1487              : 
    1488            0 :         if (loops >= 10)
    1489              :         {
    1490            0 :                 __SS__ << "Timeout waiting for SERDES RX Reset loop.";
    1491            0 :                 __SS_THROW__;
    1492              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES RX Reset loop.");
    1493            0 :         }
    1494            0 : }
    1495              : 
    1496              : /// <summary>
    1497              : /// Read if a SERDES RX reset is currently in progress
    1498              : /// </summary>
    1499              : /// <param name="link">Link to read</param>
    1500              : /// <returns>True if a SERDES reset is in progress</returns>
    1501            0 : bool DTCLib::DTC_Registers::ReadResetSERDESRX(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1502              : {
    1503            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1504            0 :         return dataSet[link + 16];
    1505              : }
    1506              : 
    1507              : /// <summary>
    1508              : /// Reset the SERDES PLL
    1509              : /// Will poll the Reset SERDES PLL Done flag until the SERDES reset is complete
    1510              : /// </summary>
    1511              : /// <param name="pll">PLL to reset</param>
    1512              : /// <param name="interval">Polling interval, in microseconds</param>
    1513            0 : void DTCLib::DTC_Registers::ResetSERDESPLL(const DTC_PLL_ID& pll, int interval)
    1514              : {
    1515            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1516            0 :         data[pll + 8] = 1;
    1517            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1518              : 
    1519            0 :         usleep(interval);
    1520              : 
    1521            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1522            0 :         data[pll + 8] = 0;
    1523            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1524            0 : }
    1525              : 
    1526              : /// <summary>
    1527              : /// Read if a SERDES PLL reset is currently in progress
    1528              : /// </summary>
    1529              : /// <param name="pll">PLL to read</param>
    1530              : /// <returns>True if a SERDES reset is in progress</returns>
    1531            0 : bool DTCLib::DTC_Registers::ReadResetSERDESPLL(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
    1532              : {
    1533            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1534            0 :         return dataSet[pll + 8];
    1535              : }
    1536              : 
    1537              : /// <summary>
    1538              : /// Reset the SERDES
    1539              : /// Will poll the Reset SERDES Done flag until the SERDES reset is complete
    1540              : /// </summary>
    1541              : /// <param name="link">Link to reset</param>
    1542              : /// <param name="interval">Polling interval, in microseconds</param>
    1543            0 : void DTCLib::DTC_Registers::ResetSERDES(DTC_Link_ID const& link, int interval)
    1544              : {
    1545            0 :         TLOG(TLVL_INFO) << __COUT_HDR__ << "Entering SERDES Reset Loop for Link " << link;
    1546            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1547            0 :         if (link == DTC_Link_ALL)
    1548              :         {
    1549            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1550            0 :                         data[i] = 1;
    1551              :         }
    1552              :         else
    1553            0 :                 data[link] = 1;
    1554            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1555              : 
    1556              :         // usleep(interval);
    1557              : 
    1558            0 :         data = ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1559            0 :         if (link == DTC_Link_ALL)
    1560              :         {
    1561            0 :                 for (uint8_t i = 0; i < 8; ++i)
    1562            0 :                         data[i] = 0;
    1563              :         }
    1564              :         else
    1565            0 :                 data[link] = 0;
    1566            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_Reset);
    1567              : 
    1568            0 :         auto resetDone = false;
    1569            0 :         uint32_t loops = 0;
    1570            0 :         while (!resetDone && ++loops < 100)
    1571              :         {
    1572            0 :                 usleep(interval);
    1573              : 
    1574            0 :                 if (link == DTC_Link_ALL)
    1575              :                 {
    1576              :                         // Ignore CFO link reset since it depends on CFO emulation mode and/or CFO presence
    1577              :                         //       For new DTC versions since December 2023, EVB is not instantiated, so also ignore
    1578              :                         //  resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0xBF) == 0xBF;
    1579              :                         //  resetDone = resetDone &&
    1580              :                         //      ( ((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0xBF) == 0xBF);
    1581            0 :                         resetDone = (ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) & 0x3F) == 0x3F;
    1582            0 :                         resetDone = resetDone &&
    1583            0 :                                                 (((ReadRegister_(CFOandDTC_Register_SERDES_ResetDone) >> 16) & 0x3F) == 0x3F);
    1584              :                 }
    1585              :                 else
    1586              :                 {
    1587            0 :                         resetDone = ReadResetRXSERDESDone(link);
    1588            0 :                         resetDone = resetDone && ReadResetTXSERDESDone(link);
    1589              :                 }
    1590            0 :                 TLOG(TLVL_INFO) << __COUT_HDR__ << "End of SERDES Reset loop=" << loops << ", done=" << std::boolalpha << resetDone;
    1591              :         }
    1592              : 
    1593            0 :         if (loops >= 100)
    1594              :         {
    1595            0 :                 __SS__ << "Timeout waiting for SERDES Reset loop=" << loops;
    1596            0 :                 __SS_THROW__;
    1597              :                 // throw DTC_IOErrorException("Timeout waiting for SERDES Reset loop.");
    1598            0 :         }
    1599            0 : }
    1600              : 
    1601            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDiagFifo(DTC_Link_ID const& link)
    1602              : {
    1603            0 :         __COUT__ << "FormatRXDiagFifo.";
    1604              :         DTC_Register reg;
    1605            0 :         switch (link)
    1606              :         {
    1607            0 :                 case DTC_Link_0:
    1608            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link0;
    1609            0 :                         break;
    1610            0 :                 case DTC_Link_1:
    1611            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link1;
    1612            0 :                         break;
    1613            0 :                 case DTC_Link_2:
    1614            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link2;
    1615            0 :                         break;
    1616            0 :                 case DTC_Link_3:
    1617            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link3;
    1618            0 :                         break;
    1619            0 :                 case DTC_Link_4:
    1620            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link4;
    1621            0 :                         break;
    1622            0 :                 case DTC_Link_5:
    1623            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_Link5;
    1624            0 :                         break;
    1625            0 :                 case DTC_Link_CFO:
    1626            0 :                         reg = DTC_Register_RXDataDiagnosticFIFO_LinkCFO;
    1627            0 :                         break;
    1628            0 :                 default: {
    1629            0 :                         __SS__ << "Invalid DTC Link";
    1630            0 :                         __SS_THROW__;
    1631              :                         // throw std::runtime_error("Invalid DTC Link");
    1632            0 :                 }
    1633              :         }
    1634              : 
    1635            0 :         auto form = CreateFormatter(reg);
    1636            0 :         form.description = "Rx Diag FIFO";
    1637            0 :         form.vals.push_back("");  // translation
    1638            0 :         for (uint8_t i = 0; i < 100; ++i)
    1639              :         {
    1640            0 :                 __COUT__ << "FormatRXDiagFifo loop." << i;
    1641            0 :                 std::ostringstream o;
    1642            0 :                 o << std::hex << std::setfill('0');
    1643            0 :                 o << "    0x" << std::setw(4) << static_cast<int>(form.address) << "  | 0x" << std::setw(8)
    1644            0 :                   << static_cast<int>(ReadRegister_(reg)) << " | ";
    1645            0 :                 form.vals.push_back(o.str());
    1646            0 :         }
    1647              : 
    1648            0 :         __COUT__ << "FormatRXDiagFifo loop done.";
    1649            0 :         return form;
    1650            0 : }
    1651              : 
    1652            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDiagFifo(DTC_Link_ID const& link)
    1653              : {
    1654              :         DTC_Register reg;
    1655            0 :         switch (link)
    1656              :         {
    1657            0 :                 case DTC_Link_0:
    1658            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link0;
    1659            0 :                         break;
    1660            0 :                 case DTC_Link_1:
    1661            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link1;
    1662            0 :                         break;
    1663            0 :                 case DTC_Link_2:
    1664            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link2;
    1665            0 :                         break;
    1666            0 :                 case DTC_Link_3:
    1667            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link3;
    1668            0 :                         break;
    1669            0 :                 case DTC_Link_4:
    1670            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link4;
    1671            0 :                         break;
    1672            0 :                 case DTC_Link_5:
    1673            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_Link5;
    1674            0 :                         break;
    1675            0 :                 case DTC_Link_CFO:
    1676            0 :                         reg = DTC_Register_TXDataDiagnosticFIFO_LinkCFO;
    1677            0 :                         break;
    1678            0 :                 default: {
    1679            0 :                         __SS__ << "Invalid DTC Link";
    1680            0 :                         __SS_THROW__;
    1681              :                         // throw std::runtime_error("Invalid DTC Link");
    1682            0 :                 }
    1683              :         }
    1684            0 :         auto form = CreateFormatter(reg);
    1685            0 :         form.description = "Tx Diag FIFO";
    1686            0 :         form.vals.push_back("");  // translation
    1687            0 :         for (uint8_t i = 0; i < 100; ++i)
    1688              :         {
    1689            0 :                 std::ostringstream o;
    1690            0 :                 o << std::hex << std::setfill('0');
    1691            0 :                 o << "    0x" << std::setw(4) << static_cast<int>(form.address) << "  | 0x" << std::setw(8)
    1692            0 :                   << static_cast<int>(ReadRegister_(reg)) << " | ";
    1693            0 :                 form.vals.push_back(o.str());
    1694            0 :         }
    1695              : 
    1696            0 :         return form;
    1697            0 : }
    1698              : 
    1699              : /// <summary>
    1700              : /// Read if a SERDES reset is currently in progress
    1701              : /// </summary>
    1702              : /// <param name="link">Link to read</param>
    1703              : /// <returns>True if a SERDES reset is in progress</returns>
    1704            0 : bool DTCLib::DTC_Registers::ReadResetSERDES(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1705              : {
    1706            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_Reset);
    1707            0 :         return dataSet[link];
    1708              : }
    1709              : 
    1710              : /// <summary>
    1711              : /// Formats the register's current value for register dumps
    1712              : /// </summary>
    1713              : /// <returns>RegisterFormatter object containing register information</returns>
    1714            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESReset()
    1715              : {
    1716            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_Reset);
    1717            0 :         form.description = "SERDES Reset";
    1718            0 :         form.vals.push_back("           ([TX,RX,Link])");
    1719            0 :         for (auto r : DTC_ROC_Links)
    1720            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ":     [" +
    1721            0 :                                                         (ReadResetSERDESTX(r, form.value) ? "x" : ".") +
    1722            0 :                                                         (ReadResetSERDESRX(r, form.value) ? "x" : ".") +
    1723            0 :                                                         (ReadResetSERDES(r, form.value) ? "x" : ".") + "]");
    1724            0 :         form.vals.push_back(std::string("CFO:        [") +
    1725            0 :                                                 (ReadResetSERDESTX(DTC_Link_CFO, form.value) ? "x" : ".") +
    1726            0 :                                                 (ReadResetSERDESRX(DTC_Link_CFO, form.value) ? "x" : ".") +
    1727            0 :                                                 (ReadResetSERDES(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
    1728            0 :         form.vals.push_back(std::string("EVB:        [") +
    1729            0 :                                                 (ReadResetSERDESTX(DTC_Link_EVB, form.value) ? "x" : ".") +
    1730            0 :                                                 (ReadResetSERDESRX(DTC_Link_EVB, form.value) ? "x" : ".") +
    1731            0 :                                                 (ReadResetSERDES(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
    1732              : 
    1733            0 :         form.vals.push_back("           ([ x = 1 (hi) ])");
    1734            0 :         for (auto r : DTC_PLLs)
    1735            0 :                 form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ": [" +
    1736            0 :                                                         (ReadResetSERDESPLL(r, form.value) ? "x" : ".") + "]");
    1737            0 :         form.vals.push_back(std::string("PLL CFO RX: [") +
    1738            0 :                                                 (ReadResetSERDESPLL(DTC_PLL_CFO_RX, form.value) ? "x" : ".") + "]");
    1739            0 :         form.vals.push_back(std::string("PLL CFO TX: [") +
    1740            0 :                                                 (ReadResetSERDESPLL(DTC_PLL_CFO_TX, form.value) ? "x" : ".") + "]");
    1741              : 
    1742            0 :         return form;
    1743            0 : }
    1744              : 
    1745              : // SERDES RX Disparity Error Register
    1746              : /// <summary>
    1747              : /// Read the SERDES RX Dispatity Error bits
    1748              : /// </summary>
    1749              : /// <param name="link">Link to read</param>
    1750              : /// <returns>DTC_SERDESRXDisparityError object with error bits</returns>
    1751            0 : DTCLib::DTC_SERDESRXDisparityError DTCLib::DTC_Registers::ReadSERDESRXDisparityError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1752              : {
    1753            0 :         return DTC_SERDESRXDisparityError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXDisparityError), link);
    1754              : }
    1755              : 
    1756              : /// <summary>
    1757              : /// Formats the register's current value for register dumps
    1758              : /// </summary>
    1759              : /// <returns>RegisterFormatter object containing register information</returns>
    1760            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityError()
    1761              : {
    1762            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXDisparityError);
    1763            0 :         form.description = "SERDES RX Disparity Error";
    1764            0 :         form.vals.push_back("       ([H,L])");
    1765            0 :         for (auto r : DTC_ROC_Links)
    1766              :         {
    1767            0 :                 auto re = ReadSERDESRXDisparityError(r, form.value);
    1768            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
    1769            0 :                                                         to_string(re.GetData()[0]) + "]");
    1770              :         }
    1771            0 :         auto ce = ReadSERDESRXDisparityError(DTC_Link_CFO, form.value);
    1772            0 :         form.vals.push_back(std::string("CFO:    [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
    1773            0 :         return form;
    1774            0 : }
    1775              : 
    1776              : // SERDES RX Character Not In Table Error Register
    1777              : /// <summary>
    1778              : /// Read the SERDES Character Not In Table Error bits
    1779              : /// </summary>
    1780              : /// <param name="link">Link to read</param>
    1781              : /// <returns>DTC_CharacterNotInTableError object with error bits</returns>
    1782            0 : DTCLib::DTC_CharacterNotInTableError DTCLib::DTC_Registers::ReadSERDESRXCharacterNotInTableError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1783              : {
    1784            0 :         return DTC_CharacterNotInTableError(val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXCharacterNotInTableError), link);
    1785              : }
    1786              : 
    1787              : /// <summary>
    1788              : /// Formats the register's current value for register dumps
    1789              : /// </summary>
    1790              : /// <returns>RegisterFormatter object containing register information</returns>
    1791            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCharacterNotInTableError()
    1792              : {
    1793            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXCharacterNotInTableError);
    1794            0 :         form.description = "SERDES RX CNIT Error";
    1795            0 :         form.vals.push_back("       ([H,L])");
    1796            0 :         for (auto r : DTC_ROC_Links)
    1797              :         {
    1798            0 :                 auto re = ReadSERDESRXCharacterNotInTableError(r, form.value);
    1799            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + to_string(re.GetData()[1]) + "," +
    1800            0 :                                                         to_string(re.GetData()[0]) + "]");
    1801              :         }
    1802            0 :         auto ce = ReadSERDESRXCharacterNotInTableError(DTC_Link_CFO, form.value);
    1803            0 :         form.vals.push_back(std::string("CFO:    [") + to_string(ce.GetData()[1]) + "," + to_string(ce.GetData()[0]) + "]");
    1804            0 :         return form;
    1805            0 : }
    1806              : 
    1807              : // SERDES Unlock Error Register
    1808              : /// <summary>
    1809              : /// Read whether the SERDES CDR Unlock Error bit is set
    1810              : /// </summary>
    1811              : /// <param name="link">Link to check</param>
    1812              : /// <returns>True if the SERDES CDR Unlock Error bit is set on the given link</returns>
    1813            0 : bool DTCLib::DTC_Registers::ReadSERDESCDRUnlockError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1814              : {
    1815            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
    1816            0 :         return dataSet[16 + link];
    1817              : }
    1818              : 
    1819              : /// <summary>
    1820              : /// Read whether the SERDES PLL Unlock Error bit is set
    1821              : /// </summary>
    1822              : /// <param name="pll">PLL to check</param>
    1823              : /// <returns>True if the SERDES PLL Unlock Error bit is set for the given PLL</returns>
    1824            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLUnlockError(const DTC_PLL_ID& pll, std::optional<uint32_t> val)
    1825              : {
    1826            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_UnlockError);
    1827            0 :         return dataSet[pll];
    1828              : }
    1829              : 
    1830              : /// <summary>
    1831              : /// Formats the register's current value for register dumps
    1832              : /// </summary>
    1833              : /// <returns>RegisterFormatter object containing register information</returns>
    1834            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESUnlockError()
    1835              : {
    1836            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_UnlockError);
    1837            0 :         form.description = "SERDES Unlock Error";
    1838            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1839            0 :         for (auto r : DTC_ROC_Links)
    1840            0 :                 form.vals.push_back(std::string("CDR Link ") + std::to_string(r) + ":    [" +
    1841            0 :                                                         (ReadSERDESCDRUnlockError(r, form.value) ? "x" : " ") + "]");
    1842            0 :         form.vals.push_back(std::string("CDR CFO:       [") + (ReadSERDESCDRUnlockError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1843            0 :         form.vals.push_back(std::string("CDR EVB:       [") + (ReadSERDESCDRUnlockError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1844            0 :         for (auto r : DTC_PLLs)
    1845            0 :                 form.vals.push_back(std::string("PLL Link ") + std::to_string(r) + ":    [" +
    1846            0 :                                                         (ReadSERDESPLLUnlockError(r, form.value) ? "x" : " ") + "]");
    1847            0 :         form.vals.push_back(std::string("PLL CFO RX:    [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_RX, form.value) ? "x" : " ") + "]");
    1848            0 :         form.vals.push_back(std::string("PLL CFO TX:    [") + (ReadSERDESPLLUnlockError(DTC_PLL_CFO_TX, form.value) ? "x" : " ") + "]");
    1849            0 :         form.vals.push_back(std::string("PLL EVB:       [") + (ReadSERDESPLLUnlockError(DTC_PLL_EVB_TXRX, form.value) ? "x" : " ") + "]");
    1850            0 :         form.vals.push_back(std::string("PLL PunchClock:[") + (ReadSERDESPLLUnlockError(DTC_PLL_PunchedClock, form.value) ? "x" : " ") + "]");
    1851            0 :         return form;
    1852            0 : }
    1853              : 
    1854              : // SERDES PLL Locked Register
    1855              : /// <summary>
    1856              : /// Read if the SERDES PLL is locked for the given SERDES link
    1857              : /// </summary>
    1858              : /// <param name="link">Link to read</param>
    1859              : /// <returns>True if the PLL is locked, false otherwise</returns>
    1860            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLLocked(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1861              : {
    1862            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLLocked);
    1863            0 :         return dataSet[link];
    1864              : }
    1865              : 
    1866              : /// <summary>
    1867              : /// Formats the register's current value for register dumps
    1868              : /// </summary>
    1869              : /// <returns>RegisterFormatter object containing register information</returns>
    1870            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLLocked()
    1871              : {
    1872            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLLocked);
    1873            0 :         form.description = "SERDES PLL Locked";
    1874            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1875            0 :         for (auto r : DTC_ROC_Links)
    1876            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ":         [" + (ReadSERDESPLLLocked(r, form.value) ? "x" : " ") + "]");
    1877            0 :         form.vals.push_back(std::string("CFO:            [") + (ReadSERDESPLLLocked(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1878            0 :         form.vals.push_back(std::string("EVB:            [") + (ReadSERDESPLLLocked(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1879            0 :         form.vals.push_back(std::string("Clock to JA:    [") + ((((form.value) >> 8) & 1) ? "x" : " ") + "]");
    1880            0 :         form.vals.push_back(std::string("Clock from JA:  [") + ((((form.value) >> 9) & 1) ? "x" : " ") + "]");
    1881            0 :         return form;
    1882            0 : }
    1883              : 
    1884              : /// <summary>
    1885              : /// Disable the SERDES PLL Power Down bit for the given link, enabling that link
    1886              : /// </summary>
    1887              : /// <param name="link">Link to set</param>
    1888            0 : void DTCLib::DTC_Registers::EnableSERDESPLL(DTC_Link_ID const& link)
    1889              : {
    1890            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1891            0 :         data[link] = 0;
    1892            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
    1893            0 : }
    1894              : 
    1895              : /// <summary>
    1896              : /// Enable the SERDES PLL Power Down bit for the given link, disabling that link
    1897              : /// </summary>
    1898              : /// <param name="link">Link to set</param>
    1899            0 : void DTCLib::DTC_Registers::DisableSERDESPLL(DTC_Link_ID const& link)
    1900              : {
    1901            0 :         std::bitset<32> data = ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1902            0 :         data[link] = 1;
    1903            0 :         WriteRegister_(data.to_ulong(), CFOandDTC_Register_SERDES_PLLPowerDown);
    1904            0 : }
    1905              : 
    1906              : /// <summary>
    1907              : /// Read the SERDES PLL Power Down bit for the given link
    1908              : /// </summary>
    1909              : /// <param name="link">link to read</param>
    1910              : /// <returns>Value of the bit</returns>
    1911            0 : bool DTCLib::DTC_Registers::ReadSERDESPLLPowerDown(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1912              : {
    1913            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_PLLPowerDown);
    1914            0 :         return data[link];
    1915              : }
    1916              : 
    1917              : /// <summary>
    1918              : /// Formats the register's current value for register dumps
    1919              : /// </summary>
    1920              : /// <returns>RegisterFormatter object containing register information</returns>
    1921            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESPLLPowerDown()
    1922              : {
    1923            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_PLLPowerDown);
    1924            0 :         form.description = "SERDES PLL Power Down";
    1925            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    1926            0 :         for (auto r : DTC_ROC_Links)
    1927            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (ReadSERDESPLLPowerDown(r, form.value) ? "x" : " ") + "]");
    1928            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadSERDESPLLPowerDown(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    1929            0 :         form.vals.push_back(std::string("EVB:    [") + (ReadSERDESPLLPowerDown(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    1930            0 :         return form;
    1931            0 : }
    1932              : 
    1933              : // SERDES RX Status Register
    1934              : /// <summary>
    1935              : /// Read the SERDES RX Status for the given SERDES Link
    1936              : /// </summary>
    1937              : /// <param name="link">Link to read</param>
    1938              : /// <returns>DTC_RXStatus object</returns>
    1939            0 : DTCLib::DTC_RXStatus DTCLib::DTC_Registers::ReadSERDESRXStatus(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1940              : {
    1941            0 :         std::bitset<3> dataSet = (val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_RXStatus)) >> 3 * link;
    1942            0 :         return static_cast<DTC_RXStatus>(dataSet.to_ulong());
    1943              : }
    1944              : 
    1945              : /// <summary>
    1946              : /// Formats the register's current value for register dumps
    1947              : /// </summary>
    1948              : /// <returns>RegisterFormatter object containing register information</returns>
    1949            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXStatus()
    1950              : {
    1951            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_RXStatus);
    1952            0 :         form.description = "SERDES RX Status";
    1953            0 :         form.vals.push_back("");  // translation
    1954            0 :         for (auto r : DTC_ROC_Links)
    1955              :         {
    1956            0 :                 auto re = ReadSERDESRXStatus(r, form.value);
    1957            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": " + DTC_RXStatusConverter(re).toString());
    1958              :         }
    1959            0 :         auto ce = ReadSERDESRXStatus(DTC_Link_CFO, form.value);
    1960            0 :         form.vals.push_back(std::string("CFO:    ") + DTC_RXStatusConverter(ce).toString());
    1961              : 
    1962            0 :         return form;
    1963            0 : }
    1964              : 
    1965              : // SERDES Reset Done Register
    1966              : /// <summary>
    1967              : /// Read the SERDES Reset RX FSM Done bit
    1968              : /// </summary>
    1969              : /// <param name="link">link to read</param>
    1970              : /// <returns>Value of the bit</returns>
    1971            0 : bool DTCLib::DTC_Registers::ReadResetRXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1972              : {
    1973            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1974            0 :         return dataSet[link + 24];
    1975              : }
    1976              : /// <summary>
    1977              : /// Read the SERDES Reset RX Done bit
    1978              : /// </summary>
    1979              : /// <param name="link">link to read</param>
    1980              : /// <returns>Value of the bit</returns>
    1981            0 : bool DTCLib::DTC_Registers::ReadResetRXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1982              : {
    1983            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1984            0 :         return dataSet[link + 16];
    1985              : }
    1986              : /// <summary>
    1987              : /// Read the SERDES Reset TX FSM Done bit
    1988              : /// </summary>
    1989              : /// <param name="link">link to read</param>
    1990              : /// <returns>Value of the bit</returns>
    1991            0 : bool DTCLib::DTC_Registers::ReadResetTXFSMSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    1992              : {
    1993            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    1994            0 :         return dataSet[link + 8];
    1995              : }
    1996              : /// <summary>
    1997              : /// Read the SERDES Reset TX Done bit
    1998              : /// </summary>
    1999              : /// <param name="link">link to read</param>
    2000              : /// <returns>Value of the bit</returns>
    2001            0 : bool DTCLib::DTC_Registers::ReadResetTXSERDESDone(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2002              : {
    2003            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_SERDES_ResetDone);
    2004            0 :         return dataSet[link];
    2005              : }
    2006              : 
    2007              : /// <summary>
    2008              : /// Formats the register's current value for register dumps
    2009              : /// </summary>
    2010              : /// <returns>RegisterFormatter object containing register information</returns>
    2011            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESResetDone()
    2012              : {
    2013            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_ResetDone);
    2014            0 :         form.description = "SERDES Reset Done";
    2015            0 :         form.vals.push_back("       ([RX FSM, RX, TX FSM, TX])");
    2016            0 :         for (auto r : DTC_ROC_Links)
    2017            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2018            0 :                                                         (ReadResetRXFSMSERDESDone(r, form.value) ? "x" : ".") +
    2019            0 :                                                         (ReadResetRXSERDESDone(r, form.value) ? "x" : ".") +
    2020            0 :                                                         (ReadResetTXFSMSERDESDone(r, form.value) ? "x" : ".") +
    2021            0 :                                                         (ReadResetTXSERDESDone(r, form.value) ? "x" : ".") + "]");
    2022            0 :         form.vals.push_back(std::string("CFO:    [") +
    2023            0 :                                                 (ReadResetRXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2024            0 :                                                 (ReadResetRXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2025            0 :                                                 (ReadResetTXFSMSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") +
    2026            0 :                                                 (ReadResetTXSERDESDone(DTC_Link_CFO, form.value) ? "x" : ".") + "]");
    2027            0 :         form.vals.push_back(std::string("EVB:    [") +
    2028            0 :                                                 (ReadResetRXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2029            0 :                                                 (ReadResetRXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2030            0 :                                                 (ReadResetTXFSMSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") +
    2031            0 :                                                 (ReadResetTXSERDESDone(DTC_Link_EVB, form.value) ? "x" : ".") + "]");
    2032            0 :         return form;
    2033            0 : }
    2034              : 
    2035              : // SFP / SERDES Status Register
    2036              : 
    2037              : /// <summary>
    2038              : /// Read the SERDES CDR Lock bit for the given SERDES Link
    2039              : /// </summary>
    2040              : /// <param name="link">Link to read</param>
    2041              : /// <returns>True if the SERDES CDR Lock bit is set</returns>
    2042            0 : bool DTCLib::DTC_Registers::ReadSERDESRXCDRLock(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2043              : {
    2044            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
    2045              : 
    2046              :         // read the lock value 20x because it might not be stable, consider unlocked if ever low
    2047            0 :         if (!val.has_value() && dataSet[link])
    2048              :         {
    2049            0 :                 for (int i = 0; i < 20; ++i)
    2050              :                 {
    2051            0 :                         std::bitset<32> tmpDataSet = ReadRegister_(DTC_Register_SERDES_RXCDRLockStatus);
    2052            0 :                         if (!tmpDataSet[link])  // override with any exception
    2053            0 :                                 return false;
    2054            0 :                         usleep(10);
    2055              :                 }
    2056              :         }
    2057            0 :         return dataSet[link];
    2058              : }
    2059              : 
    2060              : /// <summary>
    2061              : /// Formats the register's current value for register dumps
    2062              : /// </summary>
    2063              : /// <returns>RegisterFormatter object containing register information</returns>
    2064            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRLockStatus()
    2065              : {
    2066            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCDRLockStatus);
    2067            0 :         form.description = "RX CDR Lock Status";
    2068            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    2069            0 :         for (auto r : DTC_ROC_Links)
    2070              :         {
    2071            0 :                 form.vals.push_back(std::string("ROC Link ") + std::to_string(r) +
    2072            0 :                                                         " CDR Lock:   [" + (ReadSERDESRXCDRLock(r) ? "x" : " ") + "]");  // do not use form.value to force multi reread in case of instability
    2073              :         }
    2074            0 :         if (ReadCFOEmulationMode())
    2075            0 :                 form.vals.push_back(std::string("CFO Emulated CDR Lock: [") + (ReadSERDESRXCDRLock(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    2076              :         else
    2077            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
    2078              : 
    2079            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
    2080            0 :         return form;
    2081            0 : }
    2082              : 
    2083              : // DMA Timeout Preset Register
    2084              : /// <summary>
    2085              : /// Set the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
    2086              : /// The default value is 0x800
    2087              : /// </summary>
    2088              : /// <param name="preset">Maximum active time for DMA buffers</param>
    2089            0 : void DTCLib::DTC_Registers::SetDMATimeoutPreset(uint32_t preset)
    2090              : {
    2091            0 :         WriteRegister_(preset, DTC_Register_DMATimeoutPreset);
    2092            0 : }
    2093              : 
    2094              : /// <summary>
    2095              : /// Read the maximum time a DMA buffer may be active before it is sent, in 4ns ticks.
    2096              : /// The default value is 0x800
    2097              : /// </summary>
    2098              : /// <returns>Maximum active time for DMA buffers</returns>
    2099            0 : uint32_t DTCLib::DTC_Registers::ReadDMATimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_DMATimeoutPreset); }
    2100              : 
    2101              : /// <summary>
    2102              : /// Formats the register's current value for register dumps
    2103              : /// </summary>
    2104              : /// <returns>RegisterFormatter object containing register information</returns>
    2105            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDMATimeoutPreset()
    2106              : {
    2107            0 :         auto form = CreateFormatter(DTC_Register_DMATimeoutPreset);
    2108            0 :         form.description = "DMA Timeout";
    2109            0 :         std::stringstream o;
    2110            0 :         o << "0x" << std::hex << ReadDMATimeoutPreset(form.value);
    2111            0 :         form.vals.push_back(o.str());
    2112            0 :         return form;
    2113            0 : }
    2114              : 
    2115              : // ROC Timeout Preset Register
    2116              : /// <summary>
    2117              : /// Read the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
    2118              : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
    2119              : /// </summary>
    2120              : /// <returns>Timeout value</returns>
    2121            0 : uint32_t DTCLib::DTC_Registers::ReadROCTimeoutPreset(std::optional<uint32_t> val) { return val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeout); }
    2122              : 
    2123              : /// <summary>
    2124              : /// Set the timeout between the reception of a Data Header packet from a ROC and receiving all of the associated Data
    2125              : /// Packets. If a timeout occurrs, the ROCTimeoutError flag will be set. Timeout is in SERDES clock ticks
    2126              : /// </summary>
    2127              : /// <param name="preset">Timeout value. Default: 0x200000</param>
    2128            0 : void DTCLib::DTC_Registers::SetROCTimeoutPreset(uint32_t preset)
    2129              : {
    2130            0 :         WriteRegister_(preset, DTC_Register_ROCReplyTimeout);
    2131            0 : }
    2132              : 
    2133              : /// <summary>
    2134              : /// Formats the register's current value for register dumps
    2135              : /// </summary>
    2136              : /// <returns>RegisterFormatter object containing register information</returns>
    2137            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeout()
    2138              : {
    2139            0 :         auto form = CreateFormatter(DTC_Register_ROCReplyTimeout);
    2140            0 :         form.description = "ROC Reply Timeout";
    2141            0 :         std::stringstream o;
    2142            0 :         o << "0x" << std::hex << ReadROCTimeoutPreset(form.value);
    2143            0 :         form.vals.push_back(o.str());
    2144            0 :         return form;
    2145            0 : }
    2146              : 
    2147              : // ROC Timeout Error Register
    2148              : /// <summary>
    2149              : /// Clear the ROC Data Packet timeout error flag for the given SERDES link
    2150              : /// </summary>
    2151              : /// <param name="link">Link to clear</param>
    2152            0 : bool DTCLib::DTC_Registers::ReadROCTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2153              : {
    2154            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ROCReplyTimeoutError);
    2155            0 :         return data[static_cast<int>(link)];
    2156              : }
    2157              : 
    2158              : /// <summary>
    2159              : /// Read the ROC Data Packet Timeout Error Flag for the given SERDES link
    2160              : /// </summary>
    2161              : /// <param name="link">Link to read</param>
    2162              : /// <returns>True if the error flag is set, false otherwise</returns>
    2163            0 : void DTCLib::DTC_Registers::ClearROCTimeoutError(DTC_Link_ID const& link)
    2164              : {
    2165            0 :         std::bitset<32> data = 0x0;
    2166            0 :         data[link] = 1;
    2167            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ROCReplyTimeoutError);
    2168            0 : }
    2169              : 
    2170            0 : uint32_t DTCLib::DTC_Registers::ReadROCReplyTimeoutErrorRegister()
    2171              : {
    2172            0 :         return ReadRegister_(DTC_Register_ROCReplyTimeoutError);
    2173              : }
    2174              : 
    2175              : /// <summary>
    2176              : /// Formats the register's current value for register dumps
    2177              : /// </summary>
    2178              : /// <returns>RegisterFormatter object containing register information</returns>
    2179            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCReplyTimeoutError()
    2180              : {
    2181            0 :         auto form = CreateFormatter(DTC_Register_ROCReplyTimeoutError);
    2182            0 :         form.description = "ROC Reply Timeout Error";
    2183            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    2184            0 :         for (auto r : DTC_ROC_Links)
    2185              :         {
    2186            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2187            0 :                                                         (ReadROCTimeoutError(r, form.value) ? "x" : " ") + "]");
    2188              :         }
    2189            0 :         return form;
    2190            0 : }
    2191              : 
    2192              : /// <summary>
    2193              : /// Set the DTC ID and EVB Info register
    2194              : /// </summary>
    2195              : /// <returns></returns>
    2196            0 : void DTCLib::DTC_Registers::SetEVBInfo(uint8_t dtcid, uint8_t mode,
    2197              :                                                                            uint8_t partitionId, uint8_t macByte)
    2198              : {
    2199            0 :         uint32_t regVal = dtcid << 24;
    2200            0 :         regVal |= mode << 16;
    2201            0 :         regVal |= partitionId << 8;
    2202            0 :         regVal |= macByte;
    2203            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2204            0 : }
    2205              : 
    2206              : /// <summary>
    2207              : /// Set only the DTC ID within the EVB Info register
    2208              : /// </summary>
    2209              : /// <returns></returns>
    2210            0 : void DTCLib::DTC_Registers::SetDTCID(uint8_t dtcid)
    2211              : {
    2212            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0x00FFFFFF;
    2213            0 :         regVal += dtcid << 24;
    2214            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2215            0 : }
    2216              : 
    2217              : // EVB Network Partition ID / EVB Network Local MAC Index Register
    2218            0 : uint8_t DTCLib::DTC_Registers::ReadDTCID(std::optional<uint32_t> val)
    2219              : {
    2220            0 :         auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF000000;
    2221            0 :         return static_cast<uint8_t>(regVal >> 24);
    2222              : }
    2223              : 
    2224              : /// <summary>
    2225              : /// Set the EVB Mode byte
    2226              : /// </summary>
    2227              : /// <param name="mode">New Mode byte</param>
    2228            0 : void DTCLib::DTC_Registers::SetEVBMode(uint8_t mode)
    2229              : {
    2230            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFF00FFFF;
    2231            0 :         regVal += mode << 16;
    2232            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2233            0 : }
    2234              : 
    2235              : /// <summary>
    2236              : /// Read the EVB Mode byte
    2237              : /// </summary>
    2238              : /// <returns>EVB Mode byte</returns>
    2239            0 : uint8_t DTCLib::DTC_Registers::ReadEVBMode(std::optional<uint32_t> val)
    2240              : {
    2241            0 :         auto regVal = (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF0000;
    2242            0 :         return static_cast<uint8_t>(regVal >> 16);
    2243              : }
    2244              : 
    2245              : /// <summary>
    2246              : /// Set the local partition ID
    2247              : /// </summary>
    2248              : /// <param name="id">Local partition ID</param>
    2249            0 : void DTCLib::DTC_Registers::SetEVBLocalParitionID(uint8_t partitionId)
    2250              : {
    2251            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFF00FF;
    2252            0 :         regVal += partitionId << 8;
    2253            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2254            0 : }
    2255              : 
    2256              : /// <summary>
    2257              : /// Read the local partition ID
    2258              : /// </summary>
    2259              : /// <returns>Partition ID</returns>
    2260            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalParitionID(std::optional<uint32_t> val)
    2261              : {
    2262            0 :         return static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) >> 8) & 0xFF);
    2263              : }
    2264              : 
    2265              : /// <summary>
    2266              : /// Set the MAC address for the EVB network (lowest byte)
    2267              : /// </summary>
    2268              : /// <param name="macByte">MAC Address</param>
    2269            0 : void DTCLib::DTC_Registers::SetEVBLocalMACAddress(uint8_t macByte)
    2270              : {
    2271            0 :         auto regVal = ReadRegister_(DTC_Register_EVBPartitionID) & 0xFFFFFF00;
    2272            0 :         regVal += macByte;
    2273            0 :         WriteRegister_(regVal, DTC_Register_EVBPartitionID);
    2274            0 : }
    2275              : 
    2276              : /// <summary>
    2277              : /// Read the MAC address for the EVB network (lowest byte)
    2278              : /// </summary>
    2279              : /// <returns>MAC Address</returns>
    2280            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLocalMACAddress(std::optional<uint32_t> val) { return (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPartitionID)) & 0xFF; }
    2281              : 
    2282              : /// <summary>
    2283              : /// Formats the register's current value for register dumps
    2284              : /// </summary>
    2285              : /// <returns>RegisterFormatter object containing register information</returns>
    2286            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBLocalParitionIDMACIndex()
    2287              : {
    2288            0 :         auto form = CreateFormatter(DTC_Register_EVBPartitionID);
    2289            0 :         form.description = "EVB Local Partition ID / MAC Index";
    2290            0 :         form.vals.push_back("");  // translation
    2291            0 :         std::ostringstream o;
    2292            0 :         o << "DTC ID:                         0x" << std::hex << static_cast<int>(ReadDTCID(form.value));
    2293            0 :         form.vals.push_back(o.str());
    2294            0 :         o.str("");
    2295            0 :         o.clear();
    2296            0 :         o << "EVB Mode:                       0x" << std::hex << static_cast<int>(ReadEVBMode(form.value));
    2297            0 :         form.vals.push_back(o.str());
    2298            0 :         o.str("");
    2299            0 :         o.clear();
    2300            0 :         o << "EVB Parition ID:                0x" << std::hex << static_cast<int>(ReadEVBLocalParitionID(form.value));
    2301            0 :         form.vals.push_back(o.str());
    2302            0 :         o.str("");
    2303            0 :         o.clear();
    2304            0 :         auto mac = static_cast<int>(ReadEVBLocalMACAddress(form.value));
    2305            0 :         o << "EVB Self MAC Address Last Byte: 0x" << std::hex << mac << " (" << std::dec << mac << ")";
    2306            0 :         form.vals.push_back(o.str());
    2307            0 :         return form;
    2308            0 : }
    2309              : 
    2310              : /// EVB Number of Destination Nodes Register
    2311            0 : void DTCLib::DTC_Registers::SetEVBClusterInfo(uint16_t deadTime,
    2312              :                                                                                           uint8_t baseDTCAddress, uint8_t numOfDTCs)
    2313              : {
    2314            0 :         uint32_t regVal = (deadTime & 0xFFFF) << 16;
    2315            0 :         regVal |= baseDTCAddress << 8;
    2316            0 :         regVal |= numOfDTCs;
    2317            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2318            0 : }
    2319              : 
    2320              : /// <summary>
    2321              : /// 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
    2322              : /// </summary>
    2323            0 : void DTCLib::DTC_Registers::SetEVBDeadTime(uint16_t deadTime)
    2324              : {
    2325            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0x0FFFF;
    2326            0 :         regVal += (deadTime & 0xFFFF) << 16;
    2327            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2328            0 : }
    2329              : 
    2330              : /// <summary>
    2331              : /// 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
    2332              : /// </summary>
    2333            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDeadTime(std::optional<uint32_t> val)
    2334              : {
    2335            0 :         return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFFFF0000)) >> 16);
    2336              : }
    2337              : 
    2338              : /// <summary>
    2339              : /// Set the start node in the EVB cluster
    2340              : /// </summary>
    2341            0 : void DTCLib::DTC_Registers::SetEVBStartNode(uint8_t startNode)
    2342              : {
    2343            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFF00FF;
    2344            0 :         regVal += startNode << 8;
    2345            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2346            0 : }
    2347              : 
    2348              : /// <summary>
    2349              : /// Read the start node in the EVB cluster
    2350              : /// </summary>
    2351            0 : uint8_t DTCLib::DTC_Registers::ReadEVBStartNode(std::optional<uint32_t> val)
    2352              : {
    2353            0 :         return static_cast<uint8_t>((((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFF00)) >> 8);
    2354              : }
    2355              : 
    2356              : /// <summary>
    2357              : /// Set the number of destination nodes in the EVB cluster
    2358              : /// </summary>
    2359              : /// <param name="numOfNodes">Number of nodes</param>
    2360            0 : void DTCLib::DTC_Registers::SetEVBNumberOfDestinationNodes(uint8_t numOfNodes)
    2361              : {
    2362            0 :         auto regVal = ReadRegister_(DTC_Register_EVBConfiguration) & 0xFFFFFF00;
    2363            0 :         regVal += numOfNodes;
    2364            0 :         WriteRegister_(regVal, DTC_Register_EVBConfiguration);
    2365            0 : }
    2366              : 
    2367              : /// <summary>
    2368              : /// Read the number of destination nodes in the EVB cluster
    2369              : /// </summary>
    2370              : /// <returns>Number of nodes</returns>
    2371            0 : uint8_t DTCLib::DTC_Registers::ReadEVBNumberOfDestinationNodes(std::optional<uint32_t> val)
    2372              : {
    2373            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBConfiguration)) & 0xFF);
    2374              : }
    2375              : 
    2376              : /// <summary>
    2377              : /// Formats the register's current value for register dumps
    2378              : /// </summary>
    2379              : /// <returns>RegisterFormatter object containing register information</returns>
    2380            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBClusterInfo()
    2381              : {
    2382            0 :         auto form = CreateFormatter(DTC_Register_EVBConfiguration);
    2383            0 :         form.description = "EVB DTC Cluster Configuration";
    2384            0 :         form.vals.push_back("");  // translation
    2385            0 :         std::stringstream o;
    2386            0 :         o << "EVB Dead Time: " << std::dec << static_cast<int>(ReadEVBDeadTime(form.value));
    2387            0 :         form.vals.push_back(o.str());
    2388            0 :         o.str("");
    2389            0 :         o.clear();
    2390            0 :         auto startNode = static_cast<int>(ReadEVBStartNode(form.value));
    2391            0 :         o << "EVB Start Node: 0x" << std::hex << startNode << " (" << std::dec << startNode << ")";
    2392            0 :         form.vals.push_back(o.str());
    2393            0 :         o.str("");
    2394            0 :         o.clear();
    2395            0 :         o << "EVB Number of Destination Nodes: " << std::dec << static_cast<int>(ReadEVBNumberOfDestinationNodes(form.value));
    2396            0 :         form.vals.push_back(o.str());
    2397            0 :         return form;
    2398            0 : }
    2399              : 
    2400              : /// Hardware Event Building Packet Control Info Register
    2401            0 : void DTCLib::DTC_Registers::SetEVBPacketControlInfo(uint16_t idlePacketWordCount,
    2402              :                                                                                                         uint8_t interpacketGap, uint8_t loopbackCalibratedOffset)
    2403              : {
    2404            0 :         uint32_t regVal = idlePacketWordCount << 16;
    2405            0 :         regVal |= interpacketGap << 8;
    2406            0 :         regVal |= loopbackCalibratedOffset;
    2407            0 :         WriteRegister_(regVal, DTC_Register_EVBPacketControl);
    2408            0 : }
    2409              : 
    2410              : /// Read the number of words in EVB idle packets
    2411            0 : uint16_t DTCLib::DTC_Registers::ReadEVBIdlePacketWordCount(std::optional<uint32_t> val)
    2412              : {
    2413            0 :         return static_cast<uint16_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
    2414              : }
    2415              : /// Read the EVB interpacket gap in units of GbE transmit clocks
    2416            0 : uint8_t DTCLib::DTC_Registers::ReadEVBInterpacketGap(std::optional<uint32_t> val)
    2417              : {
    2418            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 8);
    2419              : }
    2420              : /// Read the DTC's EVB delay offset in units of 200MHz CFO clocks, which should be calibrated by CFO-DTC loopback
    2421            0 : uint8_t DTCLib::DTC_Registers::ReadEVBLoopbackCalibratedOffset(std::optional<uint32_t> val)
    2422              : {
    2423            0 :         return static_cast<uint8_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBPacketControl)) >> 0);
    2424              : }
    2425              : 
    2426              : /// Formats the Hardware Event Building Packet Control Info Register's current value for register dumps
    2427            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBPacketControlInfo()
    2428              : {
    2429            0 :         auto form = CreateFormatter(DTC_Register_EVBPacketControl);
    2430            0 :         form.description = "EVB Packet Control Info";
    2431            0 :         form.vals.push_back("");  // translation
    2432            0 :         std::stringstream o;
    2433            0 :         o << "Idle Packet Word Count:                           " << std::dec << static_cast<int>(ReadEVBIdlePacketWordCount(form.value));
    2434            0 :         form.vals.push_back(o.str());
    2435            0 :         o.str("");
    2436            0 :         o.clear();
    2437            0 :         o << "Interpacket Gap [GbE tx clocks]:                  " << std::dec << static_cast<int>(ReadEVBInterpacketGap(form.value));
    2438            0 :         form.vals.push_back(o.str());
    2439            0 :         o.str("");
    2440            0 :         o.clear();
    2441            0 :         o << "DTC's Loopback Calibrated Offset [200MHz clocks]: " << std::dec << static_cast<int>(ReadEVBLoopbackCalibratedOffset(form.value));
    2442            0 :         form.vals.push_back(o.str());
    2443            0 :         return form;
    2444            0 : }
    2445              : 
    2446              : /// Set the EVB idle-burst count (0x9170 [15:0]).
    2447              : /// 0 or 1 keeps the default one-idle-per-window behavior.  N sends up to N idle
    2448              : /// packets per destination window, each through the normal header/CRC/gap path.
    2449            0 : void DTCLib::DTC_Registers::SetEVBIdleBurst(uint16_t count)
    2450              : {
    2451            0 :         WriteRegister_(static_cast<uint32_t>(count), DTC_Register_EVBIdleBurst);
    2452            0 : }
    2453              : 
    2454              : /// Read the EVB idle-burst count (0x9170 [15:0])
    2455            0 : uint16_t DTCLib::DTC_Registers::ReadEVBIdleBurst(std::optional<uint32_t> val)
    2456              : {
    2457              :         return static_cast<uint16_t>(
    2458            0 :                 (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBIdleBurst)) & 0xFFFFu);
    2459              : }
    2460              : 
    2461              : /// Formats the EVB idle-burst register for register dumps
    2462            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBIdleBurst()
    2463              : {
    2464            0 :         auto form = CreateFormatter(DTC_Register_EVBIdleBurst);
    2465            0 :         form.description = "EVB Idle Burst";
    2466            0 :         form.vals.push_back("");
    2467            0 :         std::stringstream o;
    2468            0 :         o << "Idle Burst Count: " << std::dec << ReadEVBIdleBurst(form.value)
    2469            0 :           << " (0 or 1 = one per window)";
    2470            0 :         form.vals.push_back(o.str());
    2471            0 :         return form;
    2472            0 : }
    2473              : 
    2474              : /// Read the EVB resends served by this DTC's TX (0x9174 [31:16]): rewinds performed for peers
    2475            0 : uint16_t DTCLib::DTC_Registers::ReadEVBResendsServed(std::optional<uint32_t> val)
    2476              : {
    2477              :         return static_cast<uint16_t>(
    2478            0 :                 ((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBResendCount)) >> 16) & 0xFFFFu);
    2479              : }
    2480              : 
    2481              : /// Read the EVB resends requested by this DTC's RX (0x9174 [15:0]): sequence gaps that entered discard
    2482            0 : uint16_t DTCLib::DTC_Registers::ReadEVBResendsRequested(std::optional<uint32_t> val)
    2483              : {
    2484              :         return static_cast<uint16_t>(
    2485            0 :                 (val.has_value() ? *val : ReadRegister_(DTC_Register_EVBResendCount)) & 0xFFFFu);
    2486              : }
    2487              : 
    2488              : /// Formats the EVB resend-count register for register dumps
    2489            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBResendCount()
    2490              : {
    2491            0 :         auto form = CreateFormatter(DTC_Register_EVBResendCount);
    2492            0 :         form.description = "EVB Resend Count";
    2493            0 :         form.vals.push_back("");
    2494            0 :         std::stringstream o;
    2495            0 :         o << "Resends served by TX: " << std::dec << ReadEVBResendsServed(form.value);
    2496            0 :         form.vals.push_back(o.str());
    2497            0 :         o.str("");
    2498            0 :         o.clear();
    2499            0 :         o << "Resends requested by RX: " << std::dec << ReadEVBResendsRequested(form.value);
    2500            0 :         form.vals.push_back(o.str());
    2501            0 :         return form;
    2502            0 : }
    2503              : 
    2504              : /// Read theHardware Event Building Stats data based on type and DTC mac address
    2505            0 : uint32_t DTCLib::DTC_Registers::ReadEVBStats(DTC_EVBStatsType type, uint8_t dtc_mac, std::optional<uint32_t> val)
    2506              : {
    2507            0 :         if (val.has_value())                              // assum address is already setup when value is passed, and just read updated stat value
    2508            0 :                 return ReadRegister_(DTC_Register_EVBStats);  //*val;
    2509              : 
    2510            0 :         uint32_t t = static_cast<uint8_t>(type) << DTC_EVBStatsType_BRAM_TYPE_SIZE;
    2511            0 :         if (dtc_mac >= (1 << DTC_EVBStatsType_BRAM_TYPE_SIZE))
    2512              :         {
    2513            0 :                 __SS__ << "Illegal DTC MAC adress value: " << (int)dtc_mac << " must be < 2^" << DTC_EVBStatsType_BRAM_TYPE_SIZE << __E__;
    2514            0 :                 ss << otsStyleStackTrace() << __E__;
    2515            0 :                 __SS_THROW__;
    2516            0 :         }
    2517            0 :         t |= dtc_mac;  // address fully built now
    2518            0 :         __COUTT__ << "Read EVB Stat address: 0x" << std::hex << t << __E__;
    2519              : 
    2520            0 :         WriteRegister_(t, DTC_Register_EVBStats);
    2521              : 
    2522              :         // first read drains any stale capture from the TX FSM holding the BRAM port
    2523            0 :         ReadRegister_(DTC_Register_EVBStats);
    2524            0 :         return ReadRegister_(DTC_Register_EVBStats);
    2525              : }  // end ReadEVBStats()
    2526              : 
    2527              : // Get the last packet count and its timestamp for a DTC
    2528            0 : std::pair<uint32_t, std::chrono::steady_clock::time_point> DTCLib::DTC_Registers::getPacketCountInfo(uint8_t dtc) const
    2529              : {
    2530            0 :         auto i = lastPacketCount.find(dtc);
    2531            0 :         if (i != lastPacketCount.end())
    2532            0 :                 return i->second;
    2533            0 :         return {0, std::chrono::steady_clock::time_point::min()};
    2534              : }
    2535              : 
    2536              : // Update the packet count and timestamp and calculate packet rate for a DTC
    2537            0 : void DTCLib::DTC_Registers::updatePacketCount(uint8_t dtc, uint32_t currentCount)
    2538              : {
    2539            0 :         auto now = std::chrono::steady_clock::now();
    2540              : 
    2541            0 :         auto [lastCount, lastTime] = getPacketCountInfo(dtc);
    2542            0 :         if (lastTime == std::chrono::steady_clock::time_point::min())
    2543              :         {
    2544            0 :                 lastPacketCount[dtc] = {currentCount, now};
    2545            0 :                 return;
    2546              :         }
    2547              : 
    2548            0 :         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
    2549            0 :         if (ns > 1e6)
    2550              :         {
    2551            0 :                 double rate = (currentCount - lastCount) / (ns / 1e9);
    2552            0 :                 lastPacketRate[dtc] = rate;
    2553            0 :                 lastPacketCount[dtc] = {currentCount, now};
    2554              :         }
    2555              : }
    2556              : 
    2557              : // Get the most recent packet rate for a DTC
    2558            0 : double DTCLib::DTC_Registers::getLastPacketRate(uint8_t dtc) const
    2559              : {
    2560            0 :         auto i = lastPacketRate.find(dtc);
    2561            0 :         return i != lastPacketRate.end() ? i->second : 0.0;
    2562              : }
    2563              : 
    2564              : /// Formats the Hardware Event Building Stats data for all DTC mac addresses, as specified by the EVB Info 'Number Of Destination Nodes'
    2565            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBStats(DTCLib::DTC_EVBStatsType type /*  = DTC_EVBStatsType::DTC_EVBStatsType_All */)
    2566              : {
    2567            0 :         uint8_t t = static_cast<uint8_t>(type);
    2568            0 :         if (type == DTC_EVBStatsType::DTC_EVBStatsType_All)
    2569            0 :                 t = 0;
    2570            0 :         __COUTV__(t);
    2571              : 
    2572            0 :         auto form = CreateFormatter(DTC_Register_EVBStats, false /* getValue */);
    2573            0 :         form.description = "EVB Stats";
    2574            0 :         form.vals.push_back("");  // translation
    2575            0 :         std::stringstream o;
    2576              : 
    2577            0 :         uint8_t baseDTCAddress = ReadEVBStartNode();
    2578            0 :         uint8_t numOfDTCs = ReadEVBNumberOfDestinationNodes();
    2579              : 
    2580            0 :         __COUTV__(numOfDTCs);
    2581              : 
    2582            0 :         uint32_t idlePacketWordCount = (static_cast<uint32_t>(ReadRegister_(DTC_Register_EVBPacketControl)) >> 16);
    2583              : 
    2584            0 :         for (; t < DTC_EVBStatsType_BRAM_TYPE_COUNT; ++t)
    2585              :         {
    2586            0 :                 for (uint8_t d = 0; d < numOfDTCs; ++d)
    2587              :                 {
    2588            0 :                         uint32_t v = ReadEVBStats(DTC_EVBStatsType(t), d);
    2589              : 
    2590            0 :                         o << "BRAM Stat - ";
    2591            0 :                         switch (DTC_EVBStatsType(t))
    2592              :                         {
    2593            0 :                                 case DTC_EVBStatsType_RxCount:
    2594            0 :                                         if (v > 0 &&  // start time for rates as soon as there is non-zero data
    2595            0 :                                                 EVB_startDataTime ==
    2596            0 :                                                         std::chrono::steady_clock::time_point::min())
    2597            0 :                                                 EVB_startDataTime = std::chrono::steady_clock::now();
    2598              : 
    2599            0 :                                         EVB_endDataTime = std::chrono::steady_clock::now();
    2600              : 
    2601            0 :                                         o << "Received Packet Rate:                  ";
    2602            0 :                                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
    2603              : 
    2604              :                                         {
    2605            0 :                                                 auto now = std::chrono::steady_clock::now();
    2606            0 :                                                 auto [lastCount, lastTime] = getPacketCountInfo(d);
    2607              : 
    2608            0 :                                                 if (lastTime == std::chrono::steady_clock::time_point::min())
    2609              :                                                 {
    2610            0 :                                                         updatePacketCount(d, v);
    2611            0 :                                                         o << "Initializing";
    2612              :                                                 }
    2613              :                                                 else
    2614              :                                                 {
    2615            0 :                                                         auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(now - lastTime).count();
    2616              : 
    2617            0 :                                                         if (ns > 1e6)  // prevent divide by 0
    2618              :                                                         {
    2619            0 :                                                                 double rate = (v - lastCount) / (ns / 1e9);
    2620            0 :                                                                 o << rate << " Packets/s";
    2621              : 
    2622            0 :                                                                 updatePacketCount(d, v);
    2623              :                                                         }
    2624              :                                                         else
    2625            0 :                                                                 o << "T too short.";
    2626              :                                                 }
    2627              :                                         }
    2628            0 :                                         form.vals.push_back(o.str());
    2629            0 :                                         o.str("");
    2630            0 :                                         o.clear();
    2631              : 
    2632            0 :                                         o << "Bram Stat - Received Packet Count:                 ";
    2633            0 :                                         break;
    2634            0 :                                 case DTC_EVBStatsType_RxLastSequenceTag:
    2635            0 :                                         o << "Last Received Sequence Tag:            ";
    2636            0 :                                         break;
    2637            0 :                                 case DTC_EVBStatsType_RxMissingPacketCount:
    2638            0 :                                         o << "Rx Missing Packet Count:               ";
    2639            0 :                                         break;
    2640            0 :                                 case DTC_EVBStatsType_RxByteCount:
    2641            0 :                                         o << "Received Byte Rate:                    ";
    2642            0 :                                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = ";
    2643              : 
    2644            0 :                                         o << getLastPacketRate(d) * idlePacketWordCount * 8 << " Byte/s";
    2645            0 :                                         form.vals.push_back(o.str());
    2646            0 :                                         o.str("");
    2647            0 :                                         o.clear();
    2648              : 
    2649            0 :                                         o << "Bram Stat - Received Byte Count:                   ";
    2650            0 :                                         break;
    2651            0 :                                 case DTC_EVBStatsType_RxLastPacketArrival:
    2652            0 :                                         o << "Rx Last Packet Arrival [10gbe clocks]: ";
    2653            0 :                                         break;
    2654            0 :                                 case DTC_EVBStatsType_TxLastSequenceTag:
    2655            0 :                                         o << "Last Transmitted Sequence Tag:         ";
    2656            0 :                                         break;
    2657            0 :                                 case DTC_EVBStatsType_TravelTime:
    2658            0 :                                         o << "Travel Time [switch clocks]:           ";
    2659            0 :                                         break;
    2660            0 :                                 case DTC_EVBStatsType_TxIdleCount:
    2661            0 :                                         o << "TX Idle Packet Count:                  ";
    2662            0 :                                         break;
    2663            0 :                                 case DTC_EVBStatsType_RxIdleCount:
    2664            0 :                                         o << "RX Idle Packet Count:                  ";
    2665            0 :                                         break;
    2666            0 :                                 case DTC_EVBStatsType_TxPacketCount:
    2667            0 :                                         o << "TX Packet Count:                       ";
    2668            0 :                                         break;
    2669            0 :                                 case DTC_EVBStatsType_RxAckPosition:
    2670            0 :                                         o << "Rx Ack Position (peer resend feedback): ";
    2671            0 :                                         break;
    2672            0 :                                 default:
    2673            0 :                                         __SS__ << "Invalid DTC EVB Stat type: " << t << __E__;
    2674            0 :                                         __SS_THROW__;
    2675              :                         }
    2676            0 :                         o << "DTC_mac #" << (baseDTCAddress + d < 10 ? "0" : "") << std::dec << int(baseDTCAddress + d) << " = " << std::hex << "0x" << std::setw(8) << v << "\t" << std::dec << v;
    2677            0 :                         form.vals.push_back(o.str());
    2678            0 :                         o.str("");
    2679            0 :                         o.clear();
    2680              :                 }  // end DTC mac address loop
    2681            0 :                 if (type != DTC_EVBStatsType::DTC_EVBStatsType_All) break;
    2682              :         }  // end type loop
    2683              : 
    2684            0 :         return form;
    2685            0 : }  // end FormatEVBStats()
    2686              : 
    2687              : /// <summary>
    2688              : /// Read the Reset bit of the SERDES IIC Bus
    2689              : /// </summary>
    2690              : /// <returns>Reset bit value</returns>
    2691            0 : bool DTCLib::DTC_Registers::ReadSERDESOscillatorIICInterfaceReset(std::optional<uint32_t> val)
    2692              : {
    2693            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESClock_IICBusControl));
    2694            0 :         return dataSet[31];
    2695              : }
    2696              : 
    2697              : /// <summary>
    2698              : /// Reset the SERDES IIC Bus
    2699              : /// </summary>
    2700            0 : void DTCLib::DTC_Registers::ResetSERDESOscillatorIICInterface()
    2701              : {
    2702            0 :         auto bs = std::bitset<32>();
    2703            0 :         bs[31] = 1;
    2704            0 :         WriteRegister_(bs.to_ulong(), DTC_Register_SERDESClock_IICBusControl);
    2705            0 :         while (ReadSERDESOscillatorIICInterfaceReset())
    2706              :         {
    2707            0 :                 usleep(1000);
    2708              :         }
    2709            0 : }
    2710              : 
    2711              : /// <summary>
    2712              : /// Read the current SERDES Oscillator clock speed
    2713              : /// </summary>
    2714              : /// <returns>Current SERDES clock speed</returns>
    2715            0 : DTCLib::DTC_SerdesClockSpeed DTCLib::DTC_Registers::ReadSERDESOscillatorClock(std::optional<uint32_t> val)
    2716              : {
    2717              :         // DTC register definition was removed, all DTC versions only were returning constant value
    2718            0 :         auto freq = 0x09502f90;  // 156.25mhz // ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, val);
    2719              : 
    2720              :         // Clocks should be accurate to 30 ppm
    2721            0 :         if (freq > 156250000 - 4687.5 && freq < 156250000 + 4687.5) return DTC_SerdesClockSpeed_3125Gbps;
    2722            0 :         if (freq > 125000000 - 3750 && freq < 125000000 + 3750) return DTC_SerdesClockSpeed_25Gbps;
    2723            0 :         return DTC_SerdesClockSpeed_Unknown;
    2724              : }
    2725              : /// <summary>
    2726              : /// Set the SERDES Oscillator clock speed for the given SERDES transfer rate
    2727              : /// </summary>
    2728              : /// <param name="speed">Clock speed to set</param>
    2729            0 : void DTCLib::DTC_Registers::SetSERDESOscillatorClock(DTC_SerdesClockSpeed speed)
    2730              : {
    2731              :         double targetFreq;
    2732            0 :         switch (speed)
    2733              :         {
    2734            0 :                 case DTC_SerdesClockSpeed_25Gbps:
    2735            0 :                         targetFreq = 125000000.0;
    2736            0 :                         break;
    2737            0 :                 case DTC_SerdesClockSpeed_3125Gbps:
    2738            0 :                         targetFreq = 156250000.0;
    2739            0 :                         break;
    2740            0 :                 default:
    2741            0 :                         targetFreq = 0.0;
    2742            0 :                         break;
    2743              :         }
    2744            0 :         if (SetNewOscillatorFrequency(DTC_OscillatorType_SERDES, targetFreq))
    2745              :         {
    2746            0 :                 for (auto& link : DTC_ROC_Links)
    2747              :                 {
    2748            0 :                         ResetSERDES(link, 1000);
    2749              :                 }
    2750            0 :                 ResetSERDES(DTC_Link_CFO, 1000);
    2751              :                 // ResetSERDES(DTC_Link_EVB, 1000);
    2752              :         }
    2753            0 : }
    2754              : 
    2755              : /// <summary>
    2756              : /// Set the Timing Oscillator clock to a given frequency
    2757              : /// </summary>
    2758              : /// <param name="freq">Frequency to set the Timing card Oscillator clock</param>
    2759            0 : void DTCLib::DTC_Registers::SetTimingOscillatorClock(uint32_t freq)
    2760              : {
    2761            0 :         double targetFreq = freq;
    2762            0 :         if (SetNewOscillatorFrequency(DTC_OscillatorType_Timing, targetFreq))
    2763              :         {
    2764            0 :                 ResetSERDES(DTC_Link_CFO, 1000);
    2765              :                 // ResetSERDES(DTC_Link_EVB, 1000);
    2766              :         }
    2767            0 : }
    2768              : 
    2769              : // /// <summary>
    2770              : // /// Formats the register's current value for register dumps
    2771              : // /// </summary>
    2772              : // /// <returns>RegisterFormatter object containing register information</returns>
    2773              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTimingSERDESOscillatorFrequency()
    2774              : // {
    2775              : //      auto form = CreateFormatter(DTC_Register_SERDESTimingCardOscillatorFrequency);
    2776              : //      form.description = "SERDES Timing Card Oscillator Reference Frequency";
    2777              : //      std::stringstream o;
    2778              : //      o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_CFO, form.value);
    2779              : //      form.vals.push_back(o.str());
    2780              : //      return form;
    2781              : // }
    2782              : 
    2783              : // /// <summary>
    2784              : // /// Formats the register's current value for register dumps
    2785              : // /// </summary>
    2786              : // /// <returns>RegisterFormatter object containing register information</returns>
    2787              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMainBoardSERDESOscillatorFrequency()
    2788              : // {
    2789              : //      auto form = CreateFormatter(DTC_Register_SERDESReferenceClockFrequency);
    2790              : //      form.description = "SERDES Main Board Oscillator Reference Frequency";
    2791              : //      std::stringstream o;
    2792              : //      o << std::dec << ReadSERDESOscillatorReferenceFrequency(DTC_IICSERDESBusAddress_EVB, form.value);
    2793              : //      form.vals.push_back(o.str());
    2794              : //      return form;
    2795              : // }
    2796              : /// <summary>
    2797              : /// Formats the register's current value for register dumps
    2798              : /// </summary>
    2799              : /// <returns>RegisterFormatter object containing register information</returns>
    2800            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESOscillatorControl()
    2801              : {
    2802            0 :         auto form = CreateFormatter(DTC_Register_SERDESClock_IICBusControl);
    2803            0 :         form.description = "SERDES Oscillator IIC Bus Control";
    2804            0 :         form.vals.push_back(std::string("Reset:  [") + (ReadSERDESOscillatorIICInterfaceReset(form.value) ? "x" : " ") + "]");
    2805            0 :         return form;
    2806            0 : }
    2807              : 
    2808              : // FIFO Full Error Flags Registers
    2809              : /// <summary>
    2810              : /// Clear all FIFO Full Error Flags for the given link
    2811              : /// </summary>
    2812              : /// <param name="link">Link to clear</param>
    2813            0 : void DTCLib::DTC_Registers::ClearFIFOFullErrorFlags(DTC_Link_ID const& link)
    2814              : {
    2815            0 :         auto flags = ReadFIFOFullErrorFlags(link);
    2816            0 :         std::bitset<32> data0 = 0;
    2817            0 :         std::bitset<32> data1 = 0;
    2818            0 :         std::bitset<32> data2 = 0;
    2819              : 
    2820            0 :         data0[link] = flags.OutputData;
    2821            0 :         data0[link + 8] = flags.CFOLinkInput;
    2822            0 :         data0[link + 16] = flags.ReadoutRequestOutput;
    2823            0 :         data0[link + 24] = flags.DataRequestOutput;
    2824            0 :         data1[link] = flags.OtherOutput;
    2825            0 :         data1[link + 8] = flags.OutputDCS;
    2826            0 :         data1[link + 16] = flags.OutputDCSStage2;
    2827            0 :         data1[link + 24] = flags.DataInput;
    2828            0 :         data2[link] = flags.DCSStatusInput;
    2829              : 
    2830            0 :         WriteRegister_(data0.to_ulong(), DTC_Register_FIFOFullErrorFlag0);
    2831            0 :         WriteRegister_(data1.to_ulong(), DTC_Register_FIFOFullErrorFlag1);
    2832            0 :         WriteRegister_(data2.to_ulong(), DTC_Register_FIFOFullErrorFlag2);
    2833            0 : }
    2834              : 
    2835              : /// <summary>
    2836              : /// Read the FIFO Full Error/Status Flags for the given link
    2837              : /// </summary>
    2838              : /// <param name="link">Link to read</param>
    2839              : /// <returns>DTC_FIFOFullErrorFlags object</returns>
    2840            0 : DTCLib::DTC_FIFOFullErrorFlags DTCLib::DTC_Registers::ReadFIFOFullErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val0,
    2841              :                                                                                                                                                          std::optional<uint32_t> val1, std::optional<uint32_t> val2)
    2842              : {
    2843            0 :         std::bitset<32> data0 = val0.has_value() ? *val0 : ReadRegister_(DTC_Register_FIFOFullErrorFlag0);
    2844            0 :         std::bitset<32> data1 = val1.has_value() ? *val1 : ReadRegister_(DTC_Register_FIFOFullErrorFlag1);
    2845            0 :         std::bitset<32> data2 = val2.has_value() ? *val2 : ReadRegister_(DTC_Register_FIFOFullErrorFlag2);
    2846            0 :         DTC_FIFOFullErrorFlags flags;
    2847              : 
    2848            0 :         flags.OutputData = data0[link];
    2849            0 :         flags.CFOLinkInput = data0[link + 8];
    2850            0 :         flags.ReadoutRequestOutput = data0[link + 16];
    2851            0 :         flags.DataRequestOutput = data0[link + 24];
    2852            0 :         flags.OtherOutput = data1[link];
    2853            0 :         flags.OutputDCS = data1[link + 8];
    2854            0 :         flags.OutputDCSStage2 = data1[link + 16];
    2855            0 :         flags.DataInput = data1[link + 24];
    2856            0 :         flags.DCSStatusInput = data2[link];
    2857              : 
    2858            0 :         return flags;
    2859              : }
    2860              : 
    2861              : /// <summary>
    2862              : /// Formats the register's current value for register dumps
    2863              : /// </summary>
    2864              : /// <returns>RegisterFormatter object containing register information</returns>
    2865            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag0()
    2866              : {
    2867            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag0);
    2868            0 :         form.description = "FIFO Full Error Flags 0";
    2869            0 :         form.vals.push_back("       ([DataRequest, ReadoutRequest, CFOLink, OutputData])");
    2870            0 :         for (auto r : DTC_ROC_Links)
    2871              :         {
    2872            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2873            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataRequestOutput ? "x" : " ") + "," +
    2874            0 :                                                         (re.ReadoutRequestOutput ? "x" : " ") + "," + (re.CFOLinkInput ? "x" : " ") + "," +
    2875            0 :                                                         (re.OutputData ? "x" : " ") + "]");
    2876              :         }
    2877            0 :         return form;
    2878            0 : }
    2879              : 
    2880              : /// <summary>
    2881              : /// Formats the register's current value for register dumps
    2882              : /// </summary>
    2883              : /// <returns>RegisterFormatter object containing register information</returns>
    2884            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag1()
    2885              : {
    2886            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag1);
    2887            0 :         form.description = "FIFO Full Error Flags 1";
    2888            0 :         form.vals.push_back("       ([DataInput, OutputDCSStage2, OutputDCS, OtherOutput])");
    2889            0 :         for (auto r : DTC_ROC_Links)
    2890              :         {
    2891            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2892            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DataInput ? "x" : " ") + "," +
    2893            0 :                                                         (re.OutputDCSStage2 ? "x" : " ") + "," + (re.OutputDCS ? "x" : " ") + "," +
    2894            0 :                                                         (re.OtherOutput ? "x" : " ") + "]");
    2895              :         }
    2896              :         {
    2897            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
    2898            0 :                 form.vals.push_back(std::string("CFO:    [") + +(ce.DataInput ? "x" : " ") + "," +
    2899            0 :                                                         (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
    2900            0 :                                                         (ce.OtherOutput ? "x" : " ") + "]");
    2901              :         }
    2902              :         {
    2903            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
    2904            0 :                 form.vals.push_back(std::string("EVB:    [") + +(ce.DataInput ? "x" : " ") + "," +
    2905            0 :                                                         (ce.OutputDCSStage2 ? "x" : " ") + "," + (ce.OutputDCS ? "x" : " ") + "," +
    2906            0 :                                                         (ce.OtherOutput ? "x" : " ") + "]");
    2907              :         }
    2908            0 :         return form;
    2909            0 : }
    2910              : 
    2911              : /// <summary>
    2912              : /// Formats the register's current value for register dumps
    2913              : /// </summary>
    2914              : /// <returns>RegisterFormatter object containing register information</returns>
    2915            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFIFOFullErrorFlag2()
    2916              : {
    2917            0 :         auto form = CreateFormatter(DTC_Register_FIFOFullErrorFlag2);
    2918            0 :         form.description = "FIFO Full Error Flags 2";
    2919            0 :         form.vals.push_back("       ([DCSStatusInput])");
    2920            0 :         for (auto r : DTC_ROC_Links)
    2921              :         {
    2922            0 :                 auto re = ReadFIFOFullErrorFlags(r, form.value);
    2923            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" + (re.DCSStatusInput ? "x" : " ") + "]");
    2924              :         }
    2925              :         {
    2926            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_CFO, form.value);
    2927            0 :                 form.vals.push_back(std::string("CFO:    [") + (ce.DCSStatusInput ? "x" : " ") + "]");
    2928              :         }
    2929              :         {
    2930            0 :                 auto ce = ReadFIFOFullErrorFlags(DTC_Link_EVB, form.value);
    2931            0 :                 form.vals.push_back(std::string("EVB:    [") + (ce.DCSStatusInput ? "x" : " ") + "]");
    2932              :         }
    2933            0 :         return form;
    2934            0 : }
    2935              : 
    2936              : // Receive Packet Error Register
    2937              : /// <summary>
    2938              : /// Clear the Packet Error Flag for the given link
    2939              : /// </summary>
    2940              : /// <param name="link">Link to clear</param>
    2941            0 : void DTCLib::DTC_Registers::ClearPacketError(DTC_Link_ID const& link)
    2942              : {
    2943            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
    2944            0 :         data[static_cast<int>(link) + 8] = 0;
    2945            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
    2946            0 : }
    2947              : 
    2948              : /// <summary>
    2949              : /// Read the Packet Error Flag for the given link
    2950              : /// </summary>
    2951              : /// <param name="link">Link to read</param>
    2952              : /// <returns>True if the Packet Error Flag is set</returns>
    2953            0 : bool DTCLib::DTC_Registers::ReadPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2954              : {
    2955            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
    2956            0 :         return data[static_cast<int>(link) + 8];
    2957              : }
    2958              : 
    2959              : /// <summary>
    2960              : /// Clear the Packet CRC Error Flag for the given link
    2961              : /// </summary>
    2962              : /// <param name="link">Link to clear</param>
    2963            0 : void DTCLib::DTC_Registers::ClearPacketCRCError(DTC_Link_ID const& link)
    2964              : {
    2965            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_ReceivePacketError);
    2966            0 :         data[static_cast<int>(link)] = 0;
    2967            0 :         WriteRegister_(data.to_ulong(), DTC_Register_ReceivePacketError);
    2968            0 : }
    2969              : 
    2970              : /// <summary>
    2971              : /// Read the Packet CRC Error Flag for the given link
    2972              : /// </summary>
    2973              : /// <param name="link">Link to read</param>
    2974              : /// <returns>True if the Packet CRC Error Flag is set</returns>
    2975            0 : bool DTCLib::DTC_Registers::ReadPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    2976              : {
    2977            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_ReceivePacketError);
    2978            0 :         return data[static_cast<int>(link)];
    2979              : }
    2980              : 
    2981              : /// <summary>
    2982              : /// Formats the register's current value for register dumps
    2983              : /// </summary>
    2984              : /// <returns>RegisterFormatter object containing register information</returns>
    2985            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatReceivePacketError()
    2986              : {
    2987            0 :         auto form = CreateFormatter(DTC_Register_ReceivePacketError);
    2988            0 :         form.description = "Receive Packet Error";
    2989            0 :         form.vals.push_back("       ([CRC, PacketError])");
    2990            0 :         for (auto r : DTC_ROC_Links)
    2991            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    2992            0 :                                                         (ReadPacketCRCError(r, form.value) ? "x" : " ") + "," +
    2993            0 :                                                         (ReadPacketError(r, form.value) ? "x" : " ") + "]");
    2994            0 :         form.vals.push_back(std::string("CFO:    [") +
    2995            0 :                                                 (ReadPacketCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    2996            0 :                                                 (ReadPacketError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    2997            0 :         form.vals.push_back(std::string("EVB:    [") +
    2998            0 :                                                 (ReadPacketCRCError(DTC_Link_EVB, form.value) ? "x" : " ") + "," +
    2999            0 :                                                 (ReadPacketError(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    3000            0 :         return form;
    3001            0 : }
    3002              : 
    3003              : // CFO Emulation Timestamp Registers
    3004              : /// <summary>
    3005              : /// Set the starting DTC_EventWindowTag for the CFO Emulator
    3006              : /// </summary>
    3007              : /// <param name="ts">Starting Timestamp for CFO Emulation</param>
    3008            0 : void DTCLib::DTC_Registers::SetCFOEmulationTimestamp(const DTC_EventWindowTag& ts)
    3009              : {
    3010            0 :         auto timestamp = ts.GetEventWindowTag();
    3011            0 :         auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
    3012            0 :         timestamp >>= 32;
    3013            0 :         auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
    3014              : 
    3015            0 :         WriteRegister_(timestampLow, DTC_Register_CFOEmulation_TimestampLow);
    3016            0 :         WriteRegister_(timestampHigh, DTC_Register_CFOEmulation_TimestampHigh);
    3017            0 : }
    3018              : 
    3019              : /// <summary>
    3020              : /// Read the starting DTC_EventWindowTag for the CFO Emulator
    3021              : /// </summary>
    3022              : /// <returns>DTC_EventWindowTag object</returns>
    3023            0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadCFOEmulationTimestamp(std::optional<uint32_t> val)
    3024              : {
    3025            0 :         auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
    3026            0 :         DTC_EventWindowTag output;
    3027            0 :         output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh)));
    3028            0 :         return output;
    3029            0 : }
    3030              : 
    3031              : /// <summary>
    3032              : /// Formats the register's current value for register dumps
    3033              : /// </summary>
    3034              : /// <returns>RegisterFormatter object containing register information</returns>
    3035            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampLow()
    3036              : {
    3037            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampLow);
    3038            0 :         form.description = "CFO Emulation Timestamp Low";
    3039            0 :         std::stringstream o;
    3040            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampLow);
    3041            0 :         form.vals.push_back(o.str());
    3042            0 :         return form;
    3043            0 : }
    3044              : 
    3045              : /// <summary>
    3046              : /// Formats the register's current value for register dumps
    3047              : /// </summary>
    3048              : /// <returns>RegisterFormatter object containing register information</returns>
    3049            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationTimestampHigh()
    3050              : {
    3051            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_TimestampHigh);
    3052            0 :         form.description = "CFO Emulation Timestamp High";
    3053            0 :         std::stringstream o;
    3054            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_CFOEmulation_TimestampHigh);
    3055            0 :         form.vals.push_back(o.str());
    3056            0 :         return form;
    3057            0 : }
    3058              : 
    3059              : // CFO Emulation Delay Measure
    3060              : /// <summary>
    3061              : /// Read the Delay Measure acquired with the CFO Emulator Loopback Test
    3062              : /// </summary>
    3063            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationLoopbackDelayMeasure(std::optional<uint32_t> val)
    3064              : {
    3065            0 :         uint32_t readVal = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    3066            0 :         uint32_t i = 0;
    3067            0 :         while (!(readVal >> 31))
    3068              :         {
    3069            0 :                 if (i > 1000)
    3070              :                 {
    3071            0 :                         __SS__ << "Timeout looking for the CFO Emulator Loopback Test to complete... readval: 0x" << std::hex << readVal << __E__;
    3072            0 :                         __SS_THROW__;
    3073            0 :                 }
    3074              : 
    3075            0 :                 usleep(10000);
    3076            0 :                 readVal = ReadRegister_(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    3077            0 :                 ++i;
    3078              :         }
    3079            0 :         return readVal & (~(1 << 31));  // clear the Ready bit from return value
    3080              : }
    3081              : 
    3082              : /// <summary>
    3083              : /// Formats the register's current value for register dumps
    3084              : /// </summary>
    3085              : /// <returns>RegisterFormatter object containing register information</returns>
    3086            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationLoopbackDelayMeasure()
    3087              : {
    3088            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_LoopbackDelayMeasure);
    3089            0 :         form.description = "CFO Emu. Loopback Delay Measure";
    3090            0 :         std::stringstream o;
    3091            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)";
    3092            0 :         form.vals.push_back(o.str());
    3093            0 :         return form;
    3094            0 : }
    3095              : 
    3096              : // CFO Emulation Request Interval Register
    3097              : /// <summary>
    3098              : /// Set the clock interval between CFO Emulator Event Windows.
    3099              : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
    3100              : /// </summary>
    3101              : /// <param name="interval">Clock cycles between Event Window Markers</param>
    3102            0 : void DTCLib::DTC_Registers::SetCFOEmulationEventWindowInterval(uint32_t interval)
    3103              : {
    3104            0 :         WriteRegister_(interval, DTC_Register_CFOEmulation_HeartbeatInterval);
    3105            0 : }
    3106              : 
    3107              : /// <summary>
    3108              : /// Read the clock interval between CFO Emulator Event Windows.
    3109              : /// If 0, specifies to execute the On/Off Spill emulation of Event Window intervals.
    3110              : /// </summary>
    3111              : /// <returns>Clock cycles between Event Window Markers</returns>
    3112            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationEventWindowInterval(std::optional<uint32_t> val)
    3113              : {
    3114            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_HeartbeatInterval);
    3115              : }
    3116              : 
    3117              : /// <summary>
    3118              : /// Formats the register's current value for register dumps
    3119              : /// </summary>
    3120              : /// <returns>RegisterFormatter object containing register information</returns>
    3121            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationEventWindowInterval()
    3122              : {
    3123            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_HeartbeatInterval);
    3124            0 :         form.description = "CFO Emu. EWM Interval";
    3125            0 :         std::stringstream o;
    3126            0 :         o << "0x" << std::hex << ReadCFOEmulationEventWindowInterval(form.value);
    3127            0 :         form.vals.push_back(o.str());
    3128            0 :         return form;
    3129            0 : }
    3130              : 
    3131              : // CFO Emulation Number of Requests Register
    3132              : /// <summary>
    3133              : /// Set the number of Readout Requests the CFO Emulator is configured to send.
    3134              : /// A value of 0 means that the CFO Emulator will send requests continuously.
    3135              : /// </summary>
    3136              : /// <param name="NumHeartbeats">Number of Readout Requests the CFO Emulator will send</param>
    3137            0 : void DTCLib::DTC_Registers::SetCFOEmulationNumHeartbeats(uint32_t NumHeartbeats)
    3138              : {
    3139            0 :         WriteRegister_(NumHeartbeats, DTC_Register_CFOEmulation_NumHeartbeats);
    3140            0 : }
    3141              : 
    3142              : /// <summary>
    3143              : /// Reads the number of Readout Requests the CFO Emulator is configured to send.
    3144              : /// A value of 0 means that the CFO Emulator will send requests continuously.
    3145              : /// </summary>
    3146              : /// <returns>Number of Readout Requests the CFO Emulator will send</returns>
    3147            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumHeartbeats(std::optional<uint32_t> val)
    3148              : {
    3149            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumHeartbeats);
    3150              : }
    3151              : 
    3152              : /// <summary>
    3153              : /// Formats the register's current value for register dumps
    3154              : /// </summary>
    3155              : /// <returns>RegisterFormatter object containing register information</returns>
    3156            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumHeartbeats()
    3157              : {
    3158            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_NumHeartbeats);
    3159            0 :         form.description = "CFO Emulator Number Requests";
    3160            0 :         std::stringstream o;
    3161            0 :         o << "0x" << std::hex << ReadCFOEmulationNumHeartbeats(form.value);
    3162            0 :         form.vals.push_back(o.str());
    3163            0 :         return form;
    3164            0 : }
    3165              : 
    3166              : // CFO Emulation Number of Packets Registers
    3167              : /// <summary>
    3168              : /// Set the number of packets the CFO Emulator will request from the link
    3169              : /// </summary>
    3170              : /// <param name="link">Link to set</param>
    3171              : /// <param name="numPackets">Number of packets to request</param>
    3172            0 : void DTCLib::DTC_Registers::SetROCEmulationNumPackets(DTC_Link_ID const& link_in, uint16_t numPackets)
    3173              : {
    3174            0 :         uint16_t data = numPackets & 0x7FF;
    3175              :         DTC_Register reg;
    3176              : 
    3177            0 :         for (const auto& link : DTC_ROC_Links)
    3178              :         {
    3179            0 :                 if (!(link_in == DTC_Link_ALL || link_in == link))
    3180            0 :                         continue;  // skip ROC links that should not be set
    3181              : 
    3182            0 :                 switch (link)
    3183              :                 {
    3184            0 :                         case DTC_Link_0:
    3185              :                         case DTC_Link_1:
    3186            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
    3187            0 :                                 break;
    3188            0 :                         case DTC_Link_2:
    3189              :                         case DTC_Link_3:
    3190            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
    3191            0 :                                 break;
    3192            0 :                         case DTC_Link_4:
    3193              :                         case DTC_Link_5:
    3194            0 :                                 reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
    3195            0 :                                 break;
    3196            0 :                         default: {
    3197            0 :                                 __SS__ << "Illegal link " << link << " specified." << __E__;
    3198            0 :                                 __SS_THROW__;
    3199            0 :                         }
    3200              :                 }
    3201              : 
    3202            0 :                 auto regval = ReadRegister_(reg);
    3203            0 :                 auto upper = (regval & 0xFFFF0000) >> 16;
    3204            0 :                 auto lower = regval & 0x0000FFFF;
    3205            0 :                 if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
    3206              :                 {
    3207            0 :                         lower = data;
    3208              :                 }
    3209              :                 else
    3210              :                 {
    3211            0 :                         upper = data;
    3212              :                 }
    3213            0 :                 WriteRegister_((upper << 16) + lower, reg);
    3214              :         }  // end link write loop
    3215            0 : }
    3216              : 
    3217              : /// <summary>
    3218              : /// Read the requested number of packets the ROC Emulator will generate from the given link
    3219              : /// </summary>
    3220              : /// <param name="link">Link to read</param>
    3221              : /// <returns>Number of packets generated by the ROC Emulator</returns>
    3222            0 : uint16_t DTCLib::DTC_Registers::ReadROCEmulationNumPackets(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3223              : {
    3224              :         DTC_Register reg;
    3225            0 :         switch (link)
    3226              :         {
    3227            0 :                 case DTC_Link_0:
    3228              :                 case DTC_Link_1:
    3229            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks10;
    3230            0 :                         break;
    3231            0 :                 case DTC_Link_2:
    3232              :                 case DTC_Link_3:
    3233            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks32;
    3234            0 :                         break;
    3235            0 :                 case DTC_Link_4:
    3236              :                 case DTC_Link_5:
    3237            0 :                         reg = DTC_Register_ROCEmulation_NumPacketsLinks54;
    3238            0 :                         break;
    3239            0 :                 default: {
    3240            0 :                         __SS__ << "Illegal link " << link << " specified." << __E__;
    3241            0 :                         __SS_THROW__;
    3242            0 :                 }
    3243              :         }
    3244              : 
    3245            0 :         auto regval = val.has_value() ? *val : ReadRegister_(reg);
    3246            0 :         auto upper = (regval & 0xFFFF0000) >> 16;
    3247            0 :         auto lower = regval & 0x0000FFFF;
    3248            0 :         if (link == DTC_Link_0 || link == DTC_Link_2 || link == DTC_Link_4)
    3249              :         {
    3250            0 :                 return static_cast<uint16_t>(lower);
    3251              :         }
    3252            0 :         return static_cast<uint16_t>(upper);
    3253              : }
    3254              : 
    3255              : /// <summary>
    3256              : /// Formats the register's current value for register dumps
    3257              : /// </summary>
    3258              : /// <returns>RegisterFormatter object containing register information</returns>
    3259            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink01()
    3260              : {
    3261            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks10);
    3262            0 :         form.description = "ROC Emulator Num Packets R0,1";
    3263            0 :         form.vals.push_back("");  // translation
    3264            0 :         std::stringstream o;
    3265            0 :         o << "Link 0: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_0, form.value);
    3266            0 :         form.vals.push_back(o.str());
    3267            0 :         o.str("");
    3268            0 :         o.clear();
    3269            0 :         o << "Link 1: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_1, form.value);
    3270            0 :         form.vals.push_back(o.str());
    3271            0 :         return form;
    3272            0 : }
    3273              : 
    3274              : /// <summary>
    3275              : /// Formats the register's current value for register dumps
    3276              : /// </summary>
    3277              : /// <returns>RegisterFormatter object containing register information</returns>
    3278            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink23()
    3279              : {
    3280            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks32);
    3281            0 :         form.description = "ROC Emulator Num Packets R2,3";
    3282            0 :         form.vals.push_back("");  // translation
    3283            0 :         std::stringstream o;
    3284            0 :         o << "Link 2: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_2, form.value);
    3285            0 :         form.vals.push_back(o.str());
    3286            0 :         o.str("");
    3287            0 :         o.clear();
    3288            0 :         o << "Link 3: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_3, form.value);
    3289            0 :         form.vals.push_back(o.str());
    3290            0 :         return form;
    3291            0 : }
    3292              : 
    3293              : /// <summary>
    3294              : /// Formats the register's current value for register dumps
    3295              : /// </summary>
    3296              : /// <returns>RegisterFormatter object containing register information</returns>
    3297            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulationNumPacketsLink45()
    3298              : {
    3299            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulation_NumPacketsLinks54);
    3300            0 :         form.description = "ROC Emulator Num Packets R4,5";
    3301            0 :         form.vals.push_back("");  // translation
    3302            0 :         std::stringstream o;
    3303            0 :         o << "Link 4: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_4, form.value);
    3304            0 :         form.vals.push_back(o.str());
    3305            0 :         o.str("");
    3306            0 :         o.clear();
    3307            0 :         o << "Link 5: 0x" << std::hex << ReadROCEmulationNumPackets(DTC_Link_5, form.value);
    3308            0 :         form.vals.push_back(o.str());
    3309            0 :         return form;
    3310            0 : }
    3311              : 
    3312              : // CFO Emulation Number of Null Heartbeats Register
    3313              : /// <summary>
    3314              : /// Set the number of null heartbeats the CFO Emulator will generate following the requested ones
    3315              : /// </summary>
    3316              : /// <param name="count">Number of null heartbeats to generate</param>
    3317            0 : void DTCLib::DTC_Registers::SetCFOEmulationNumNullHeartbeats(const uint32_t& count)
    3318              : {
    3319            0 :         WriteRegister_(count, DTC_Register_CFOEmulation_NumNullHeartbeats);
    3320            0 : }
    3321              : 
    3322              : /// <summary>
    3323              : /// Read the requested number of null heartbeats that will follow the configured heartbeats from the CFO Emulator
    3324              : /// </summary>
    3325              : /// <returns>Number of null heartbeats to follow "live" heartbeats</returns>
    3326            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulationNumNullHeartbeats(std::optional<uint32_t> val)
    3327              : {
    3328            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_NumNullHeartbeats);
    3329              : }
    3330              : 
    3331              : /// <summary>
    3332              : /// Formats the register's current value for register dumps
    3333              : /// </summary>
    3334              : /// <returns>RegisterFormatter object containing register information</returns>
    3335            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationNumNullHeartbeats()
    3336              : {
    3337            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_NumNullHeartbeats);
    3338            0 :         form.description = "CFO Emulator Num Null Heartbeats";
    3339            0 :         form.vals.push_back(std::to_string(ReadCFOEmulationNumNullHeartbeats(form.value)));
    3340            0 :         return form;
    3341            0 : }
    3342              : 
    3343            0 : void DTCLib::DTC_Registers::SetCFOEventModeRequiredMask(const uint32_t& mask)
    3344              : {
    3345            0 :         WriteRegister_(mask, DTC_Register_CFOEventModeRequiredMask);
    3346            0 : }
    3347            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEventModeRequiredMask(std::optional<uint32_t> val)
    3348              : {
    3349            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEventModeRequiredMask);
    3350              : }
    3351            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEventModeRequiredMask()
    3352              : {
    3353            0 :         auto form = CreateFormatter(DTC_Register_CFOEventModeRequiredMask);
    3354            0 :         form.description = "CFO Emulation Event Mode Required Mask";
    3355            0 :         std::stringstream o;
    3356            0 :         o << "0x" << std::hex << ReadCFOEventModeRequiredMask(form.value);
    3357            0 :         form.vals.push_back(o.str());
    3358            0 :         return form;
    3359            0 : }
    3360              : 
    3361              : // CFO Emulation Event Mode Bytes Registers
    3362              : /// <summary>
    3363              : /// Set the CFO Emulation Event Mode 48 bits
    3364              : /// </summary>
    3365            0 : void DTCLib::DTC_Registers::SetCFOEmulationEventMode(const uint64_t& eventMode)
    3366              : {
    3367            0 :         WriteRegister_(eventMode, DTC_Register_CFOEmulation_EventMode1);
    3368            0 :         WriteRegister_(eventMode >> 32, DTC_Register_CFOEmulation_EventMode2);
    3369            0 : }
    3370            0 : uint64_t DTCLib::DTC_Registers::ReadCFOEmulationEventMode()
    3371              : {
    3372            0 :         uint64_t eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode2);
    3373            0 :         eventMode = ReadRegister_(DTC_Register_CFOEmulation_EventMode1) |
    3374            0 :                                 (eventMode << 32);
    3375            0 :         return eventMode;
    3376              : }
    3377              : 
    3378              : /// <summary>
    3379              : /// Set the given CFO Emulation Mode byte to the given value
    3380              : /// </summary>
    3381              : /// <param name="byteNum">Byte to set. Valid range is 0-5</param>
    3382              : /// <param name="data">Data for byte</param>
    3383            0 : void DTCLib::DTC_Registers::SetCFOEmulationModeByte(const uint8_t& byteNum, uint8_t data)
    3384              : {
    3385              :         DTC_Register reg;
    3386            0 :         if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
    3387              :         {
    3388            0 :                 reg = DTC_Register_CFOEmulation_EventMode1;
    3389              :         }
    3390            0 :         else if (byteNum == 4 || byteNum == 5)
    3391              :         {
    3392            0 :                 reg = DTC_Register_CFOEmulation_EventMode2;
    3393              :         }
    3394              :         else
    3395              :         {
    3396            0 :                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3397            0 :                 __SS_THROW__;
    3398            0 :         }
    3399            0 :         auto regVal = ReadRegister_(reg);
    3400              : 
    3401            0 :         switch (byteNum)
    3402              :         {
    3403            0 :                 case 0:
    3404            0 :                         regVal = (regVal & 0xFFFFFF00) + data;
    3405            0 :                         break;
    3406            0 :                 case 1:
    3407            0 :                         regVal = (regVal & 0xFFFF00FF) + (data << 8);
    3408            0 :                         break;
    3409            0 :                 case 2:
    3410            0 :                         regVal = (regVal & 0xFF00FFFF) + (data << 16);
    3411            0 :                         break;
    3412            0 :                 case 3:
    3413            0 :                         regVal = (regVal & 0x00FFFFFF) + (data << 24);
    3414            0 :                         break;
    3415            0 :                 case 4:
    3416            0 :                         regVal = (regVal & 0xFF00) + data;
    3417            0 :                         break;
    3418            0 :                 case 5:
    3419            0 :                         regVal = (regVal & 0x00FF) + (data << 8);
    3420            0 :                         break;
    3421            0 :                 default:
    3422              :                         // impossible
    3423              :                         {
    3424            0 :                                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3425            0 :                                 __SS_THROW__;
    3426            0 :                         }
    3427              :         }
    3428              : 
    3429            0 :         WriteRegister_(regVal, reg);
    3430            0 : }
    3431              : 
    3432              : /// <summary>
    3433              : /// Read the given CFO Emulation Mode byte
    3434              : /// </summary>
    3435              : /// <param name="byteNum">Byte to read. Valid range is 0-5</param>
    3436              : /// <returns>Current value of the mode byte</returns>
    3437            0 : uint8_t DTCLib::DTC_Registers::ReadCFOEmulationModeByte(const uint8_t& byteNum, std::optional<uint32_t> val)
    3438              : {
    3439              :         DTC_Register reg;
    3440            0 :         if (byteNum == 0 || byteNum == 1 || byteNum == 2 || byteNum == 3)
    3441              :         {
    3442            0 :                 reg = DTC_Register_CFOEmulation_EventMode1;
    3443              :         }
    3444            0 :         else if (byteNum == 4 || byteNum == 5)
    3445              :         {
    3446            0 :                 reg = DTC_Register_CFOEmulation_EventMode2;
    3447              :         }
    3448              :         else
    3449              :         {
    3450            0 :                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3451            0 :                 __SS_THROW__;
    3452            0 :         }
    3453            0 :         auto regVal = val.has_value() ? *val : ReadRegister_(reg);
    3454              : 
    3455            0 :         switch (byteNum)
    3456              :         {
    3457            0 :                 case 0:
    3458            0 :                         return static_cast<uint8_t>(regVal & 0xFF);
    3459            0 :                 case 1:
    3460            0 :                         return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
    3461            0 :                 case 2:
    3462            0 :                         return static_cast<uint8_t>((regVal & 0xFF0000) >> 16);
    3463            0 :                 case 3:
    3464            0 :                         return static_cast<uint8_t>((regVal & 0xFF000000) >> 24);
    3465            0 :                 case 4:
    3466            0 :                         return static_cast<uint8_t>(regVal & 0xFF);
    3467            0 :                 case 5:
    3468            0 :                         return static_cast<uint8_t>((regVal & 0xFF00) >> 8);
    3469            0 :                 default:
    3470              :                         // impossible
    3471              :                         {
    3472            0 :                                 __SS__ << "Illegal byte index requested: " << byteNum << ". The Emulated Event Mode is only 6 bytes." << __E__;
    3473            0 :                                 __SS_THROW__;
    3474            0 :                         }
    3475              :         }
    3476              : }
    3477              : 
    3478              : /// <summary>
    3479              : /// Formats the register's current value for register dumps
    3480              : /// </summary>
    3481              : /// <returns>RegisterFormatter object containing register information</returns>
    3482            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes03()
    3483              : {
    3484            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode1);
    3485            0 :         form.description = "CFO Emulation Event Mode Bytes 0-3";
    3486            0 :         form.vals.push_back("");  // translation
    3487            0 :         std::ostringstream o;
    3488            0 :         o << "Byte 0: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(0, form.value));
    3489            0 :         form.vals.push_back(o.str());
    3490            0 :         o.str("");
    3491            0 :         o.clear();
    3492            0 :         o << "Byte 1: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(1, form.value));
    3493            0 :         form.vals.push_back(o.str());
    3494            0 :         o.str("");
    3495            0 :         o.clear();
    3496            0 :         o << "Byte 2: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(2, form.value));
    3497            0 :         form.vals.push_back(o.str());
    3498            0 :         o.str("");
    3499            0 :         o.clear();
    3500            0 :         o << "Byte 3: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(3, form.value));
    3501            0 :         form.vals.push_back(o.str());
    3502            0 :         return form;
    3503            0 : }
    3504              : 
    3505              : /// <summary>
    3506              : /// Formats the register's current value for register dumps
    3507              : /// </summary>
    3508              : /// <returns>RegisterFormatter object containing register information</returns>
    3509            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationModeBytes45()
    3510              : {
    3511            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_EventMode2);
    3512            0 :         form.description = "CFO Emulation Event Mode Bytes 4-5";
    3513            0 :         form.vals.push_back("");  // translation
    3514            0 :         std::ostringstream o;
    3515            0 :         o << "Byte 4: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(4, form.value));
    3516            0 :         form.vals.push_back(o.str());
    3517            0 :         o.str("");
    3518            0 :         o.clear();
    3519            0 :         o << "Byte 5: 0x" << std::hex << static_cast<int>(ReadCFOEmulationModeByte(5, form.value));
    3520            0 :         form.vals.push_back(o.str());
    3521            0 :         o.str("");
    3522            0 :         o.clear();
    3523            0 :         return form;
    3524            0 : }
    3525              : 
    3526              : /// <summary>
    3527              : /// Set the DebugType used by the CFO Emulator
    3528              : /// </summary>
    3529              : /// <param name="type">The DTC_DebugType the CFO Emulator will fill into Readout Requests</param>
    3530              : // void DTCLib::DTC_Registers::SetCFOEmulationDebugType(DTC_DebugType type)
    3531              : //{
    3532              : //      std::bitset<32> data = type & 0xF;
    3533              : //      data[16] = ReadDebugPacketMode();
    3534              : //      WriteRegister_(data.to_ulong(), DTC_Register_DebugPacketType);
    3535              : // }
    3536              : 
    3537              : /// <summary>
    3538              : /// Read the DebugType field filled into Readout Requests generated by the CFO Emulator
    3539              : /// </summary>
    3540              : /// <returns>The DTC_DebugType used by the CFO Emulator</returns>
    3541              : // DTCLib::DTC_DebugType DTCLib::DTC_Registers::ReadCFOEmulationDebugType(std::optional<uint32_t> val)
    3542              : //{
    3543              : //      return static_cast<DTC_DebugType>((0xFFFF & val.has_value()) ? *val : ReadRegister_(DTC_Register_DebugPacketType));
    3544              : // }
    3545              : 
    3546              : /// <summary>
    3547              : /// Formats the register's current value for register dumps
    3548              : /// </summary>
    3549              : /// <returns>RegisterFormatter object containing register information</returns>
    3550              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulationDebugPacketType()
    3551              : //{
    3552              : //      auto form = CreateFormatter(DTC_Register_DebugPacketType);
    3553              : //      form.description = "CFO Emulation Debug Packet Type";
    3554              : //      form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3555              : //      form.vals.push_back(std::string("Debug Mode: [") + (ReadDebugPacketMode(form.value) ? "x" : " ") + "]");
    3556              : //      std::stringstream o;
    3557              : //      o << "Debug Packet Type: 0x" << std::hex << ReadCFOEmulationDebugType(form.value);
    3558              : //      form.vals.push_back(o.str());
    3559              : //      return form;
    3560              : // }
    3561              : 
    3562              : // RX Packet Count Error Flags Register
    3563              : /// <summary>
    3564              : /// Read the RX Packet Count Error flag for the given link
    3565              : /// </summary>
    3566              : /// <param name="link">Link to read</param>
    3567              : /// <returns>Whether the RX Packet Count Error flag is set on the link</returns>
    3568            0 : bool DTCLib::DTC_Registers::ReadRXPacketCountErrorFlags(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3569              : {
    3570            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
    3571            0 :         return dataSet[link];
    3572              : }
    3573              : 
    3574              : /// <summary>
    3575              : /// Clear the RX Packet Count Error flag for the given link
    3576              : /// </summary>
    3577              : /// <param name="link">Link to clear</param>
    3578            0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags(DTC_Link_ID const& link)
    3579              : {
    3580            0 :         std::bitset<32> dataSet;
    3581            0 :         dataSet[link] = true;
    3582            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
    3583            0 : }
    3584              : 
    3585              : /// <summary>
    3586              : /// Clear all RX Packet Count Error Flags
    3587              : /// </summary>
    3588            0 : void DTCLib::DTC_Registers::ClearRXPacketCountErrorFlags()
    3589              : {
    3590            0 :         std::bitset<32> dataSet = ReadRegister_(DTC_Register_RXPacketCountErrorFlags);
    3591            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_RXPacketCountErrorFlags);
    3592            0 : }
    3593              : 
    3594              : /// <summary>
    3595              : /// Formats the register's current value for register dumps
    3596              : /// </summary>
    3597              : /// <returns>RegisterFormatter object containing register information</returns>
    3598            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXPacketCountErrorFlags()
    3599              : {
    3600            0 :         auto form = CreateFormatter(DTC_Register_RXPacketCountErrorFlags);
    3601            0 :         form.description = "RX Packet Count Error Flags";
    3602            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3603            0 :         for (auto r : DTC_ROC_Links)
    3604            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    3605            0 :                                                         (ReadRXPacketCountErrorFlags(r, form.value) ? "x" : " ") + "]");
    3606            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadRXPacketCountErrorFlags(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    3607            0 :         form.vals.push_back(std::string("EVB:    [") + (ReadRXPacketCountErrorFlags(DTC_Link_EVB, form.value) ? "x" : " ") + "]");
    3608            0 :         return form;
    3609            0 : }
    3610              : 
    3611              : // Detector Emulator DMA Count Register
    3612              : /// <summary>
    3613              : /// Set the number of DMAs that the Detector Emulator will generate when enabled
    3614              : /// </summary>
    3615              : /// <param name="count">The number of DMAs that the Detector Emulator will generate when enabled</param>
    3616            0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMACount(uint32_t count)
    3617              : {
    3618            0 :         WriteRegister_(count, DTC_Register_DetEmulation_DMACount);
    3619            0 : }
    3620              : 
    3621              : /// <summary>
    3622              : /// Read the number of DMAs that the Detector Emulator will generate
    3623              : /// </summary>
    3624              : /// <returns>The number of DMAs that the Detector Emulator will generate</returns>
    3625            0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMACount(std::optional<uint32_t> val)
    3626              : {
    3627            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DMACount);
    3628              : }
    3629              : 
    3630              : /// <summary>
    3631              : /// Formats the register's current value for register dumps
    3632              : /// </summary>
    3633              : /// <returns>RegisterFormatter object containing register information</returns>
    3634            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMACount()
    3635              : {
    3636            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DMACount);
    3637            0 :         form.description = "DetEmu DMA Count";
    3638            0 :         std::stringstream o;
    3639            0 :         o << "0x" << std::hex << ReadDetectorEmulationDMACount(form.value);
    3640            0 :         form.vals.push_back(o.str());
    3641            0 :         return form;
    3642            0 : }
    3643              : 
    3644              : // Detector Emulator DMA Delay Counter Register
    3645              : /// <summary>
    3646              : /// Set the delay between DMAs in Detector Emulator mode
    3647              : /// </summary>
    3648              : /// <param name="count">Delay between DMAs in Detector Emulation mode, in 4ns ticks</param>
    3649            0 : void DTCLib::DTC_Registers::SetDetectorEmulationDMADelayCount(uint32_t count)
    3650              : {
    3651            0 :         WriteRegister_(count, DTC_Register_DetEmulation_DelayCount);
    3652            0 : }
    3653              : 
    3654              : /// <summary>
    3655              : /// Read the amount of the delay between DMAs in Detector Emulator mode
    3656              : /// </summary>
    3657              : /// <returns>The amount of the delay between DMAs in Detector Emulator mode, in 4ns ticks</returns>
    3658            0 : uint32_t DTCLib::DTC_Registers::ReadDetectorEmulationDMADelayCount(std::optional<uint32_t> val)
    3659              : {
    3660            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DelayCount);
    3661              : }
    3662              : 
    3663              : /// <summary>
    3664              : /// Formats the register's current value for register dumps
    3665              : /// </summary>
    3666              : /// <returns>RegisterFormatter object containing register information</returns>
    3667            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationDMADelayCount()
    3668              : {
    3669            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DelayCount);
    3670            0 :         form.description = "DetEmu DMA Delay Count";
    3671            0 :         std::stringstream o;
    3672            0 :         o << "0x" << std::hex << ReadDetectorEmulationDMADelayCount(form.value);
    3673            0 :         form.vals.push_back(o.str());
    3674            0 :         return form;
    3675            0 : }
    3676              : 
    3677              : /// <summary>
    3678              : /// Enable Detector Emulator Mode. This sends all DMA writes to DMA channel 0 (DAQ) to DDR memory
    3679              : /// </summary>
    3680            0 : void DTCLib::DTC_Registers::EnableDetectorEmulatorMode()
    3681              : {
    3682            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3683            0 :         data[0] = 1;
    3684            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3685            0 : }
    3686              : 
    3687              : /// <summary>
    3688              : /// Disable sending DMA data to DDR memory
    3689              : /// </summary>
    3690            0 : void DTCLib::DTC_Registers::DisableDetectorEmulatorMode()
    3691              : {
    3692            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3693            0 :         data[0] = 0;
    3694            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3695            0 : }
    3696              : 
    3697              : /// <summary>
    3698              : /// Read whether writes to DMA Channel 0 will be loaded into DDR memory
    3699              : /// </summary>
    3700              : /// <returns>Whether the Detector Emulator Mode bit is set</returns>
    3701            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorMode(std::optional<uint32_t> val)
    3702              : {
    3703            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
    3704            0 :         return data[0];
    3705              : }
    3706              : 
    3707              : /// <summary>
    3708              : /// Enable the Detector Emulator (Playback Mode)
    3709              : /// This assumes that data has been loaded into DDR memory using DMA Channel 0 before enabling.
    3710              : /// </summary>
    3711            0 : void DTCLib::DTC_Registers::EnableDetectorEmulator()
    3712              : {
    3713            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control0);
    3714            0 :         data[1] = 1;
    3715            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control0);
    3716            0 : }
    3717              : 
    3718              : /// <summary>
    3719              : /// Turn off the Detector Emulator (Playback Mode)
    3720              : /// </summary>
    3721            0 : void DTCLib::DTC_Registers::DisableDetectorEmulator()
    3722              : {
    3723            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DetEmulation_Control1);
    3724            0 :         data[1] = 1;
    3725            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DetEmulation_Control1);
    3726            0 : }
    3727              : 
    3728              : /// <summary>
    3729              : /// Read whether the Detector Emulator is enabled
    3730              : /// </summary>
    3731              : /// <returns>Whether the Detector Emulator is enabled</returns>
    3732            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnable(std::optional<uint32_t> val)
    3733              : {
    3734            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control0);
    3735            0 :         return data[1];
    3736              : }
    3737              : 
    3738              : /// <summary>
    3739              : /// Read whether a Detector Emulator Disable operation is in progress
    3740              : /// </summary>
    3741              : /// <returns>Whether the Detector Emulator Enable Clear bit is set</returns>
    3742            0 : bool DTCLib::DTC_Registers::ReadDetectorEmulatorEnableClear(std::optional<uint32_t> val)
    3743              : {
    3744            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_Control1);
    3745            0 :         return data[1];
    3746              : }
    3747              : 
    3748              : /// <summary>
    3749              : /// Clear the "Detector Emulator In Use" virtual register
    3750              : /// </summary>
    3751            0 : void DTCLib::DTC_Registers::ClearDetectorEmulatorInUse()
    3752              : {
    3753            0 :         DisableDetectorEmulator();
    3754            0 :         DisableDetectorEmulatorMode();
    3755            0 :         ResetDDRWriteAddress();
    3756            0 :         ResetDDRReadAddress();
    3757            0 :         SetDDRDataLocalStartAddress(0);
    3758            0 :         SetDDRDataLocalEndAddress(0x7000000);
    3759            0 :         usingDetectorEmulator_ = false;
    3760            0 : }
    3761              : 
    3762              : /// <summary>
    3763              : /// Formats the register's current value for register dumps
    3764              : /// </summary>
    3765              : /// <returns>RegisterFormatter object containing register information</returns>
    3766            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl0()
    3767              : {
    3768            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_Control0);
    3769            0 :         form.description = "Detector Emulation Control 0";
    3770            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    3771            0 :         form.vals.push_back(std::string("Detector Emulation Enable: [") + (ReadDetectorEmulatorEnable(form.value) ? "x" : " ") + "]");
    3772            0 :         form.vals.push_back(std::string("Detector Emulation Mode:   [") + (ReadDetectorEmulatorMode(form.value) ? "x" : " ") + "]");
    3773            0 :         return form;
    3774            0 : }
    3775              : 
    3776              : /// <summary>
    3777              : /// Formats the register's current value for register dumps
    3778              : /// </summary>
    3779              : /// <returns>RegisterFormatter object containing register information</returns>
    3780            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDetectorEmulationControl1()
    3781              : {
    3782            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_Control1);
    3783            0 :         form.description = "Detector Emulation Control 1";
    3784            0 :         form.vals.push_back(std::string("Detector Emulation Enable Clear: [") +
    3785            0 :                                                 (ReadDetectorEmulatorEnableClear(form.value) ? "x" : " ") + "]");
    3786            0 :         return form;
    3787            0 : }
    3788              : 
    3789              : // DDR Event Data Local Start Address Register
    3790              : /// <summary>
    3791              : /// Set the DDR Data Start Address
    3792              : /// DDR Addresses are in bytes and must be 64-bit aligned
    3793              : /// </summary>
    3794              : /// <param name="address">Start address for the DDR data section</param>
    3795            0 : void DTCLib::DTC_Registers::SetDDRDataLocalStartAddress(uint32_t address)
    3796              : {
    3797            0 :         WriteRegister_(address, DTC_Register_DetEmulation_DataStartAddress);
    3798            0 : }
    3799              : 
    3800              : /// <summary>
    3801              : /// Read the DDR Data Start Address
    3802              : /// </summary>
    3803              : /// <returns>The current DDR data start address</returns>
    3804            0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalStartAddress(std::optional<uint32_t> val)
    3805              : {
    3806            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataStartAddress);
    3807              : }
    3808              : 
    3809              : /// <summary>
    3810              : /// Formats the register's current value for register dumps
    3811              : /// </summary>
    3812              : /// <returns>RegisterFormatter object containing register information</returns>
    3813            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalStartAddress()
    3814              : {
    3815            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DataStartAddress);
    3816            0 :         form.description = "DDR Event Data Local Start Address";
    3817            0 :         std::stringstream o;
    3818            0 :         o << "0x" << std::hex << ReadDDRDataLocalStartAddress(form.value);
    3819            0 :         form.vals.push_back(o.str());
    3820            0 :         return form;
    3821            0 : }
    3822              : 
    3823              : // DDR Event Data Local End Address Register
    3824              : /// <summary>
    3825              : /// Set the end address for the DDR data section
    3826              : /// DDR Addresses are in bytes and must be 64-bit aligned
    3827              : /// </summary>
    3828              : /// <param name="address"></param>
    3829            0 : void DTCLib::DTC_Registers::SetDDRDataLocalEndAddress(uint32_t address)
    3830              : {
    3831            0 :         WriteRegister_(address, DTC_Register_DetEmulation_DataEndAddress);
    3832            0 : }
    3833              : 
    3834              : /// <summary>
    3835              : /// Read the current end address for the DDR Data section
    3836              : /// </summary>
    3837              : /// <returns>End address for the DDR data section</returns>
    3838            0 : uint32_t DTCLib::DTC_Registers::ReadDDRDataLocalEndAddress(std::optional<uint32_t> val)
    3839              : {
    3840            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_DetEmulation_DataEndAddress);
    3841              : }
    3842              : 
    3843              : /// <summary>
    3844              : /// Formats the register's current value for register dumps
    3845              : /// </summary>
    3846              : /// <returns>RegisterFormatter object containing register information</returns>
    3847            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRDataLocalEndAddress()
    3848              : {
    3849            0 :         auto form = CreateFormatter(DTC_Register_DetEmulation_DataEndAddress);
    3850            0 :         form.description = "DDR Event Data Local End Address";
    3851            0 :         std::stringstream o;
    3852            0 :         o << "0x" << std::hex << ReadDDRDataLocalEndAddress(form.value);
    3853            0 :         form.vals.push_back(o.str());
    3854            0 :         return form;
    3855            0 : }
    3856              : 
    3857            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulatorInterpacketDelay(std::optional<uint32_t> val)
    3858              : {
    3859            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_DataRequestDelay);
    3860              : }
    3861              : 
    3862            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulatorInterpacketDelay()
    3863              : {
    3864            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_DataRequestDelay);
    3865            0 :         form.description = "CFO Emulator Data Request Interpacket Delay";
    3866            0 :         std::stringstream o;
    3867            0 :         o << std::dec << ReadCFOEmulatorInterpacketDelay(form.value) << " * 5 ns";
    3868            0 :         form.vals.push_back(o.str());
    3869            0 :         return form;
    3870            0 : }
    3871              : 
    3872              : /// <summary>
    3873              : /// Read the current maximum Ethernet payload size
    3874              : /// </summary>
    3875              : /// <returns>The current maximum Ethernet payload size</returns>
    3876            0 : uint32_t DTCLib::DTC_Registers::ReadEthernetPayloadSize(std::optional<uint32_t> val)
    3877              : {
    3878            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EthernetFramePayloadSize);
    3879              : }
    3880              : 
    3881              : /// <summary>
    3882              : /// Set the maximum Ethernet payload size, in bytes. Maximum is 1492 bytes.
    3883              : /// </summary>
    3884              : /// <param name="size">Maximum Ethernet payload size, in bytes</param>
    3885            0 : void DTCLib::DTC_Registers::SetEthernetPayloadSize(uint32_t size)
    3886              : {
    3887            0 :         if (size > 1492)
    3888              :         {
    3889            0 :                 size = 1492;
    3890              :         }
    3891            0 :         WriteRegister_(size, DTC_Register_EthernetFramePayloadSize);
    3892            0 : }
    3893              : 
    3894              : /// <summary>
    3895              : /// Formats the register's current value for register dumps
    3896              : /// </summary>
    3897              : /// <returns>RegisterFormatter object containing register information</returns>
    3898            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEthernetPayloadSize()
    3899              : {
    3900            0 :         auto form = CreateFormatter(DTC_Register_EthernetFramePayloadSize);
    3901            0 :         form.description = "Ethernet Frame Payload Max Size";
    3902            0 :         std::stringstream o;
    3903            0 :         o << std::dec << ReadEthernetPayloadSize(form.value) << " bytes";
    3904            0 :         form.vals.push_back(o.str());
    3905            0 :         return form;
    3906            0 : }
    3907              : 
    3908            0 : uint32_t DTCLib::DTC_Registers::ReadCFOEmulation40MHzMarkerInterval(std::optional<uint32_t> val)
    3909              : {
    3910            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3911              : }
    3912              : 
    3913            0 : void DTCLib::DTC_Registers::SetCFOEmulation40MHzMarkerInterval(uint32_t interval)
    3914              : {
    3915            0 :         WriteRegister_(interval, DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3916            0 : }
    3917              : 
    3918            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOEmulation40MHzMarkerInterval()
    3919              : {
    3920            0 :         auto form = CreateFormatter(DTC_Register_CFOEmulation_40MHzClockMarkerInterval);
    3921            0 :         form.description = "CFO Emulation 40MHz Marker Interval";
    3922            0 :         std::stringstream o;
    3923            0 :         o << "0x" << std::hex << ReadCFOEmulation40MHzMarkerInterval(form.value);
    3924            0 :         form.vals.push_back(o.str());
    3925            0 :         return form;
    3926            0 : }
    3927              : 
    3928              : // bool DTCLib::DTC_Registers::ReadCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3929              : // {
    3930              : //      std::bitset<32> dataSet = val.has_value()?*val:ReadRegister_(DTC_Register_CFOMarkerEnables);
    3931              : //      return dataSet[link + 8];
    3932              : // }
    3933              : 
    3934              : // void DTCLib::DTC_Registers::SetCFOEmulationEventStartMarkerEnable(DTC_Link_ID const& link, bool enable)
    3935              : // {
    3936              : //      std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
    3937              : //      data[link + 8] = enable;
    3938              : //      WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
    3939              : // }
    3940              : 
    3941            0 : bool DTCLib::DTC_Registers::ReadCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3942              : {
    3943            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOMarkerEnables);
    3944            0 :         return dataSet[link];
    3945              : }
    3946              : 
    3947            0 : void DTCLib::DTC_Registers::SetCFO40MHzClockMarkerEnable(DTC_Link_ID const& link, bool enable)
    3948              : {
    3949            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_CFOMarkerEnables);
    3950            0 :         if (link == DTC_Link_ALL)
    3951              :         {
    3952            0 :                 for (uint8_t i = 0; i < 6; ++i)  // just ROC links
    3953            0 :                         data[i] = enable;
    3954              :         }
    3955              :         else
    3956            0 :                 data[link] = enable;
    3957            0 :         WriteRegister_(data.to_ulong(), DTC_Register_CFOMarkerEnables);
    3958            0 : }
    3959              : 
    3960            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFO40MHzClockMarkerEnables()
    3961              : {
    3962            0 :         auto form = CreateFormatter(CFOandDTC_Register_SERDES_LoopbackEnable);
    3963            0 :         form.description = "CFO Emulation Marker Enables";
    3964              :         // form.vals.push_back("        [Event Start, 40 MHz]");
    3965            0 :         form.vals.push_back("        [40 MHz Clock Marker]");
    3966            0 :         for (auto r : DTC_ROC_Links)
    3967            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    3968              :                                                         // (ReadCFOEventStartMarkerEnable(r, form.value) ? "x" : " ") + "," +
    3969            0 :                                                         (ReadCFO40MHzClockMarkerEnable(r, form.value) ? "x" : " ") + "]");
    3970            0 :         return form;
    3971            0 : }
    3972              : 
    3973            0 : uint8_t DTCLib::DTC_Registers::ReadROCCommaLimit(std::optional<uint32_t> val)
    3974              : {
    3975            0 :         return static_cast<uint8_t>(val.has_value() ? *val : ReadRegister_(DTC_Register_ROCFinishThreshold));
    3976              : }
    3977              : 
    3978            0 : void DTCLib::DTC_Registers::SetROCCommaLimit(uint8_t limit)
    3979              : {
    3980            0 :         uint32_t data = ReadRegister_(DTC_Register_ROCFinishThreshold) & 0xFFFFFF00;
    3981            0 :         data += limit;
    3982            0 :         WriteRegister_(data, DTC_Register_ROCFinishThreshold);
    3983            0 : }
    3984              : 
    3985            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCFinishThreshold()
    3986              : {
    3987            0 :         auto form = CreateFormatter(DTC_Register_ROCFinishThreshold);
    3988            0 :         form.description = "ROC Finish Threshold";
    3989            0 :         std::stringstream o;
    3990            0 :         o << "ROC Comma Limit: 0x" << std::hex << static_cast<int>(ReadROCCommaLimit(form.value));
    3991            0 :         form.vals.push_back(o.str());
    3992            0 :         return form;
    3993            0 : }
    3994              : 
    3995            0 : bool DTCLib::DTC_Registers::ReadTXPRBSForceError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    3996              : {
    3997            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl));
    3998            0 :         return dataSet[link + 24];
    3999              : }
    4000              : 
    4001            0 : void DTCLib::DTC_Registers::SetTXPRBSForceError(DTC_Link_ID const& link)
    4002              : {
    4003            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
    4004            0 :         dataSet[link + 24] = 1;
    4005            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
    4006            0 : }
    4007              : 
    4008            0 : void DTCLib::DTC_Registers::ClearTXPRBSForceError(DTC_Link_ID const& link)
    4009              : {
    4010            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_TXPRBSControl));
    4011            0 :         dataSet[link + 24] = 0;
    4012            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_TXPRBSControl);
    4013            0 : }
    4014              : 
    4015            0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadTXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4016              : {
    4017            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_TXPRBSControl);
    4018            0 :         auto masked = (data >> link) & 0x7;
    4019            0 :         return static_cast<DTC_PRBSMode>(masked);
    4020              : }
    4021              : 
    4022            0 : void DTCLib::DTC_Registers::SetTXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
    4023              : {
    4024            0 :         auto data = ReadRegister_(DTC_Register_TXPRBSControl);
    4025            0 :         auto masked = data & ~(0x7 << link);
    4026            0 :         auto newMode = static_cast<uint32_t>(mode);
    4027            0 :         WriteRegister_(masked + (newMode << link), DTC_Register_TXPRBSControl);
    4028            0 : }
    4029              : 
    4030            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESTXPRBSControl()
    4031              : {
    4032            0 :         auto form = CreateFormatter(DTC_Register_TXPRBSControl);
    4033            0 :         form.description = "SERDES TX PRBS Control";
    4034            0 :         form.vals.push_back("       ([Force Error, Mode])");
    4035            0 :         for (auto r : DTC_ROC_Links)
    4036            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    4037            0 :                                                         (ReadTXPRBSForceError(r, form.value) ? "x" : " ") + "," +
    4038            0 :                                                         (DTC_PRBSModeConverter(ReadTXPRBSMode(r, form.value)).toString()) + "]");
    4039            0 :         form.vals.push_back(std::string("CFO:    [") + (ReadTXPRBSForceError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    4040            0 :                                                 (DTC_PRBSModeConverter(ReadTXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
    4041            0 :         return form;
    4042            0 : }
    4043              : 
    4044            0 : bool DTCLib::DTC_Registers::ReadRXPRBSError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4045              : {
    4046            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl));
    4047            0 :         return dataSet[link + 24];
    4048              : }
    4049              : 
    4050            0 : DTCLib::DTC_PRBSMode DTCLib::DTC_Registers::ReadRXPRBSMode(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4051              : {
    4052            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_RXPRBSControl);
    4053            0 :         auto masked = (data >> link) & 0x7;
    4054            0 :         return static_cast<DTC_PRBSMode>(masked);
    4055              : }
    4056              : 
    4057            0 : void DTCLib::DTC_Registers::SetRXPRBSMode(DTC_Link_ID const& link, DTC_PRBSMode mode)
    4058              : {
    4059            0 :         auto data = ReadRegister_(DTC_Register_RXPRBSControl);
    4060            0 :         auto masked = data & ~(0x7 << link);
    4061            0 :         auto newMode = static_cast<uint32_t>(mode);
    4062            0 :         WriteRegister_(masked + (newMode << link), DTC_Register_RXPRBSControl);
    4063            0 : }
    4064              : 
    4065            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSControl()
    4066              : {
    4067            0 :         auto form = CreateFormatter(DTC_Register_RXPRBSControl);
    4068            0 :         form.description = "SERDES RX PRBS Control";
    4069            0 :         form.vals.push_back("       ([Error, Mode])");
    4070            0 :         for (auto r : DTC_ROC_Links)
    4071            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    4072            0 :                                                         (ReadRXPRBSError(r, form.value) ? "x" : " ") + "," +
    4073            0 :                                                         (DTC_PRBSModeConverter(ReadRXPRBSMode(r, form.value)).toString()) + "]");
    4074            0 :         form.vals.push_back(std::string("CFO:    [") +
    4075            0 :                                                 (ReadRXPRBSError(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    4076            0 :                                                 (DTC_PRBSModeConverter(ReadRXPRBSMode(DTC_Link_CFO, form.value)).toString()) + "]");
    4077            0 :         return form;
    4078            0 : }
    4079              : 
    4080            0 : bool DTCLib::DTC_Registers::ReadEventModeTableEnable(std::optional<uint32_t> val)
    4081              : {
    4082            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4083            0 :         return dataSet[16];
    4084              : }
    4085              : 
    4086            0 : void DTCLib::DTC_Registers::SetEventModeTableEnable()
    4087              : {
    4088            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4089            0 :         dataSet[16] = 1;
    4090            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
    4091            0 : }
    4092              : 
    4093            0 : void DTCLib::DTC_Registers::ClearEventModeTableEnable()
    4094              : {
    4095            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_EventModeLookupTableControl));
    4096            0 :         dataSet[16] = 0;
    4097            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_EventModeLookupTableControl);
    4098            0 : }
    4099              : 
    4100            0 : uint8_t DTCLib::DTC_Registers::ReadEventModeLookupByteSelect(std::optional<uint32_t> val)
    4101              : {
    4102            0 :         auto data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventModeLookupTableControl);
    4103            0 :         auto masked = (data) & 0x7;
    4104            0 :         return static_cast<uint8_t>(masked);
    4105              : }
    4106              : 
    4107            0 : void DTCLib::DTC_Registers::SetEventModeLookupByteSelect(uint8_t byte)
    4108              : {
    4109            0 :         auto data = ReadRegister_(DTC_Register_EventModeLookupTableControl);
    4110            0 :         auto masked = data & 0xFFF8;
    4111            0 :         WriteRegister_(masked + (byte & 0x7), DTC_Register_EventModeLookupTableControl);
    4112            0 : }
    4113              : 
    4114            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventModeLookupTableControl()
    4115              : {
    4116            0 :         auto form = CreateFormatter(DTC_Register_EventModeLookupTableControl);
    4117            0 :         form.description = "Event Mode Lookup Table Control";
    4118            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4119            0 :         form.vals.push_back(std::string("Enabled:  [") +
    4120            0 :                                                 (ReadEventModeTableEnable(form.value) ? "x" : " ") + "]");
    4121            0 :         form.vals.push_back(std::string("Byte:          [") +
    4122            0 :                                                 std::to_string(ReadEventModeLookupByteSelect(form.value)) + "]");
    4123            0 :         return form;
    4124            0 : }
    4125              : 
    4126            0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestComplete(std::optional<uint32_t> val)
    4127              : {
    4128            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
    4129            0 :         return dataSet[8];
    4130              : }
    4131              : 
    4132            0 : bool DTCLib::DTC_Registers::ReadDDRMemoryTestError(std::optional<uint32_t> val)
    4133              : {
    4134            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_DD3TestRegister));
    4135            0 :         return dataSet[0];
    4136              : }
    4137              : 
    4138            0 : void DTCLib::DTC_Registers::ClearDDRMemoryTestError()
    4139              : {
    4140            0 :         WriteRegister_(1, DTC_Register_DD3TestRegister);
    4141            0 : }
    4142              : 
    4143            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRMemoryTestRegister()
    4144              : {
    4145            0 :         auto form = CreateFormatter(DTC_Register_DD3TestRegister);
    4146            0 :         form.description = "DDR3 Memory Test";
    4147            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4148            0 :         form.vals.push_back(std::string("Test Complete:  [") +
    4149            0 :                                                 (ReadDDRMemoryTestComplete(form.value) ? "x" : " ") + "]");
    4150            0 :         form.vals.push_back(std::string("Error:          [") +
    4151            0 :                                                 (ReadDDRMemoryTestError(form.value) ? "x" : " ") + "]");
    4152            0 :         return form;
    4153            0 : }
    4154              : 
    4155              : // SERDES Serial Inversion Enable Register
    4156              : /// <summary>
    4157              : /// Read the Invert SERDES RX Input bit
    4158              : /// </summary>
    4159              : /// <param name="link">Link to read</param>
    4160              : /// <returns>Whether the Invert SERDES RX Input bit is set</returns>
    4161            0 : bool DTCLib::DTC_Registers::ReadInvertSERDESRXInput(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4162              : {
    4163            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4164            0 :         return data[link + 8];
    4165              : }
    4166              : /// <summary>
    4167              : /// Set the Invert SERDES RX Input bit
    4168              : /// </summary>
    4169              : /// <param name="link">Link to set</param>
    4170              : /// <param name="invert">Whether to invert</param>
    4171            0 : void DTCLib::DTC_Registers::SetInvertSERDESRXInput(DTC_Link_ID const& link, bool invert)
    4172              : {
    4173            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4174            0 :         data[link + 8] = invert;
    4175            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
    4176            0 : }
    4177              : /// <summary>
    4178              : /// Read the Invert SERDES TX Output bit
    4179              : /// </summary>
    4180              : /// <param name="link">Link to read</param>
    4181              : /// <returns>Whether the Invert SERDES TX Output bit is set</returns>
    4182            0 : bool DTCLib::DTC_Registers::ReadInvertSERDESTXOutput(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4183              : {
    4184            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4185            0 :         return data[link];
    4186              : }
    4187              : /// <summary>
    4188              : /// Set the Invert SERDES TX Output bit
    4189              : /// </summary>
    4190              : /// <param name="link">Link to set</param>
    4191              : /// <param name="invert">Whether to invert</param>
    4192            0 : void DTCLib::DTC_Registers::SetInvertSERDESTXOutput(DTC_Link_ID const& link, bool invert)
    4193              : {
    4194            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SERDESTXRXInvertEnable);
    4195            0 :         data[link] = invert;
    4196            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SERDESTXRXInvertEnable);
    4197            0 : }
    4198              : /// <summary>
    4199              : /// Formats the register's current value for register dumps
    4200              : /// </summary>
    4201              : /// <returns>RegisterFormatter object containing register information</returns>
    4202            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESSerialInversionEnable()
    4203              : {
    4204            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    4205            0 :         form.description = "SERDES Serial Inversion Enable";
    4206            0 :         form.vals.push_back("       ([Input, Output])");
    4207            0 :         for (auto r : DTC_ROC_Links)
    4208            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    4209            0 :                                                         (ReadInvertSERDESRXInput(r, form.value) ? "x" : " ") + "," +
    4210            0 :                                                         (ReadInvertSERDESTXOutput(r, form.value) ? "x" : " ") + "]");
    4211            0 :         form.vals.push_back(std::string("CFO:    [") +
    4212            0 :                                                 (ReadInvertSERDESRXInput(DTC_Link_CFO, form.value) ? "x" : " ") + "," +
    4213            0 :                                                 (ReadInvertSERDESTXOutput(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    4214              : 
    4215            0 :         return form;
    4216            0 : }
    4217              : 
    4218              : // Jitter Attenuator CSR Register
    4219              : /// <summary>
    4220              : /// Read the value of the Jitter Attenuator Select
    4221              : /// </summary>
    4222              : /// <returns>Jitter Attenuator Select value</returns>
    4223            0 : std::bitset<2> DTCLib::DTC_Registers::ReadJitterAttenuatorSelect(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR); }
    4224              : 
    4225              : /// <summary>
    4226              : /// Set the Jitter Attenuator Select bits. JA reset only needed after a power cycle
    4227              : /// </summary>
    4228              : /// <param name="data">Value to set</param>
    4229            0 : void DTCLib::DTC_Registers::SetJitterAttenuatorSelect(std::bitset<2> data, bool alsoResetJA /* = false */) { CFOandDTC_Registers::SetJitterAttenuatorSelect(DTC_Register_JitterAttenuatorCSR, data, alsoResetJA); }
    4230              : 
    4231              : /// <summary>
    4232              : /// Read the Jitter Attenuator Reset bit
    4233              : /// </summary>
    4234              : /// <returns>Value of the Jitter Attenuator Reset bit</returns>
    4235            0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorReset(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorReset(DTC_Register_JitterAttenuatorCSR, val); }
    4236            0 : bool DTCLib::DTC_Registers::ReadJitterAttenuatorLocked(std::optional<uint32_t> val) { return CFOandDTC_Registers::ReadJitterAttenuatorLocked(DTC_Register_JitterAttenuatorCSR, val); }
    4237              : 
    4238              : /// <summary>
    4239              : /// Reset the Jitter Attenuator
    4240              : /// </summary>
    4241            0 : void DTCLib::DTC_Registers::ResetJitterAttenuator() { CFOandDTC_Registers::ResetJitterAttenuator(DTC_Register_JitterAttenuatorCSR); }
    4242              : 
    4243              : /// <summary>
    4244              : /// Formats the register's current value for register dumps
    4245              : /// </summary>
    4246              : /// <returns>RegisterFormatter object containing register information</returns>
    4247            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorCSR() { return CFOandDTC_Registers::FormatJitterAttenuatorCSR(DTC_Register_JitterAttenuatorCSR); }
    4248              : 
    4249              : // SFP IIC Registers
    4250              : 
    4251              : /// <summary>
    4252              : /// Read the Reset bit of the SFP IIC Bus
    4253              : /// </summary>
    4254              : /// <returns>Reset bit value</returns>
    4255            0 : bool DTCLib::DTC_Registers::ReadSFPIICInterfaceReset(std::optional<uint32_t> val)
    4256              : {
    4257            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SFP_IICBusControl));
    4258            0 :         return dataSet[31];
    4259              : }
    4260              : /// <summary>
    4261              : /// Reset the SFP IIC Bus
    4262              : /// </summary>
    4263            0 : void DTCLib::DTC_Registers::ResetSFPIICInterface()
    4264              : {
    4265            0 :         auto bs = std::bitset<32>();
    4266            0 :         bs[31] = 1;
    4267            0 :         WriteRegister_(bs.to_ulong(), DTC_Register_SFP_IICBusControl);
    4268            0 :         while (ReadSFPIICInterfaceReset())
    4269              :         {
    4270            0 :                 usleep(1000);
    4271              :         }
    4272            0 : }
    4273              : /// <summary>
    4274              : /// Write a value to the SFP IIC Bus
    4275              : /// </summary>
    4276              : /// <param name="device">Device address</param>
    4277              : /// <param name="address">Register address</param>
    4278              : /// <param name="data">Data to write</param>
    4279            0 : void DTCLib::DTC_Registers::WriteSFPIICInterface(uint8_t device, uint8_t address, uint8_t data)
    4280              : {
    4281            0 :         uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16) + (data << 8);
    4282            0 :         WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
    4283            0 :         WriteRegister_(0x1, DTC_Register_SFP_IICBusHigh);
    4284            0 :         while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x1)
    4285              :         {
    4286            0 :                 usleep(1000);
    4287              :         }
    4288            0 : }
    4289              : /// <summary>
    4290              : /// Read a value from the SFP IIC Bus
    4291              : /// </summary>
    4292              : /// <param name="device">Device address</param>
    4293              : /// <param name="address">Register address</param>
    4294              : /// <returns>Value of register</returns>
    4295            0 : uint8_t DTCLib::DTC_Registers::ReadSFPIICInterface(uint8_t device, uint8_t address)
    4296              : {
    4297            0 :         uint32_t reg_data = (static_cast<uint8_t>(device) << 24) + (address << 16);
    4298            0 :         WriteRegister_(reg_data, DTC_Register_SFP_IICBusLow);
    4299            0 :         WriteRegister_(0x2, DTC_Register_SFP_IICBusHigh);
    4300            0 :         while (ReadRegister_(DTC_Register_SFP_IICBusHigh) == 0x2)
    4301              :         {
    4302            0 :                 usleep(1000);
    4303              :         }
    4304            0 :         auto data = ReadRegister_(DTC_Register_SFP_IICBusLow);
    4305            0 :         return static_cast<uint8_t>(data);
    4306              : }
    4307              : 
    4308              : /// <summary>
    4309              : /// Formats the register's current value for register dumps
    4310              : /// </summary>
    4311              : /// <returns>RegisterFormatter object containing register information</returns>
    4312            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICControl()
    4313              : {
    4314            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusControl);
    4315            0 :         form.description = "SFP Oscillator IIC Bus Control";
    4316            0 :         form.vals.push_back(std::string("Reset:  [") + (ReadSFPIICInterfaceReset(form.value) ? "x" : " ") + "]");
    4317            0 :         return form;
    4318            0 : }
    4319              : /// <summary>
    4320              : /// Formats the register's current value for register dumps
    4321              : /// </summary>
    4322              : /// <returns>RegisterFormatter object containing register information</returns>
    4323            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterLow()
    4324              : {
    4325            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusLow);
    4326            0 :         form.description = "SFP Oscillator IIC Bus Low";
    4327            0 :         form.vals.push_back("");  // translation
    4328            0 :         auto data = form.value;
    4329            0 :         std::ostringstream s1, s2, s3, s4;
    4330            0 :         s1 << "Device:     " << std::showbase << std::hex << ((data & 0xFF000000) >> 24);
    4331            0 :         form.vals.push_back(s1.str());
    4332            0 :         s2 << "ASFPess:    " << std::showbase << std::hex << ((data & 0xFF0000) >> 16);
    4333            0 :         form.vals.push_back(s2.str());
    4334            0 :         s3 << "Write Data: " << std::showbase << std::hex << ((data & 0xFF00) >> 8);
    4335            0 :         form.vals.push_back(s3.str());
    4336            0 :         s4 << "Read Data:  " << std::showbase << std::hex << (data & 0xFF);
    4337            0 :         form.vals.push_back(s4.str());
    4338            0 :         return form;
    4339            0 : }
    4340              : /// <summary>
    4341              : /// Formats the register's current value for register dumps
    4342              : /// </summary>
    4343              : /// <returns>RegisterFormatter object containing register information</returns>
    4344            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPIICParameterHigh()
    4345              : {
    4346            0 :         auto form = CreateFormatter(DTC_Register_SFP_IICBusHigh);
    4347            0 :         auto data = form.value;
    4348            0 :         form.description = "SFP Oscillator IIC Bus High";
    4349            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4350            0 :         form.vals.push_back(std::string("Write:  [") + (data & 0x1 ? "x" : " ") + "]");
    4351            0 :         form.vals.push_back(std::string("Read:   [") + (data & 0x2 ? "x" : " ") + "]");
    4352            0 :         return form;
    4353            0 : }
    4354              : 
    4355            0 : uint32_t DTCLib::DTC_Registers::ReadRetransmitRequestCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4356              : {
    4357            0 :         switch (link)
    4358              :         {
    4359            0 :                 case DTC_Link_0:
    4360            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link0);
    4361            0 :                 case DTC_Link_1:
    4362            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link1);
    4363            0 :                 case DTC_Link_2:
    4364            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link2);
    4365            0 :                 case DTC_Link_3:
    4366            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link3);
    4367            0 :                 case DTC_Link_4:
    4368            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link4);
    4369            0 :                 case DTC_Link_5:
    4370            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RetransmitRequestCount_Link5);
    4371            0 :                 default: {
    4372            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4373            0 :                         __SS_THROW__;
    4374            0 :                 }
    4375              :         }
    4376              : }
    4377            0 : void DTCLib::DTC_Registers::ClearRetransmitRequestCount(DTC_Link_ID const& link)
    4378              : {
    4379            0 :         switch (link)
    4380              :         {
    4381            0 :                 case DTC_Link_0:
    4382            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link0);
    4383            0 :                         break;
    4384            0 :                 case DTC_Link_1:
    4385            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link1);
    4386            0 :                         break;
    4387            0 :                 case DTC_Link_2:
    4388            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link2);
    4389            0 :                         break;
    4390            0 :                 case DTC_Link_3:
    4391            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link3);
    4392            0 :                         break;
    4393            0 :                 case DTC_Link_4:
    4394            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link4);
    4395            0 :                         break;
    4396            0 :                 case DTC_Link_5:
    4397            0 :                         WriteRegister_(1, DTC_Register_RetransmitRequestCount_Link5);
    4398            0 :                         break;
    4399            0 :                 default: {
    4400            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4401            0 :                         __SS_THROW__;
    4402            0 :                 }
    4403              :         }
    4404            0 : }
    4405              : 
    4406              : /// <summary>
    4407              : /// Formats the register's current value for register dumps
    4408              : /// </summary>
    4409              : /// <returns>RegisterFormatter object containing register information</returns>
    4410            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink0()
    4411              : {
    4412            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link0);
    4413            0 :         form.description = "ROC Retransmit Request Count Link 0";
    4414            0 :         std::stringstream o;
    4415            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_0, form.value);
    4416            0 :         form.vals.push_back(o.str());
    4417            0 :         return form;
    4418            0 : }
    4419              : 
    4420              : /// <summary>
    4421              : /// Formats the register's current value for register dumps
    4422              : /// </summary>
    4423              : /// <returns>RegisterFormatter object containing register information</returns>
    4424            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink1()
    4425              : {
    4426            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link1);
    4427            0 :         form.description = "ROC Retransmit Request Count Link 1";
    4428            0 :         std::stringstream o;
    4429            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_1, form.value);
    4430            0 :         form.vals.push_back(o.str());
    4431            0 :         return form;
    4432            0 : }
    4433              : 
    4434              : /// <summary>
    4435              : /// Formats the register's current value for register dumps
    4436              : /// </summary>
    4437              : /// <returns>RegisterFormatter object containing register information</returns>
    4438            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink2()
    4439              : {
    4440            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link2);
    4441            0 :         form.description = "ROC Retransmit Request Count Link 2";
    4442            0 :         std::stringstream o;
    4443            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_2, form.value);
    4444            0 :         form.vals.push_back(o.str());
    4445            0 :         return form;
    4446            0 : }
    4447              : 
    4448              : /// <summary>
    4449              : /// Formats the register's current value for register dumps
    4450              : /// </summary>
    4451              : /// <returns>RegisterFormatter object containing register information</returns>
    4452            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink3()
    4453              : {
    4454            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link3);
    4455            0 :         form.description = "ROC Retransmit Request Count Link 3";
    4456            0 :         std::stringstream o;
    4457            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_3, form.value);
    4458            0 :         form.vals.push_back(o.str());
    4459            0 :         return form;
    4460            0 : }
    4461              : 
    4462              : /// <summary>
    4463              : /// Formats the register's current value for register dumps
    4464              : /// </summary>
    4465              : /// <returns>RegisterFormatter object containing register information</returns>
    4466            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink4()
    4467              : {
    4468            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link4);
    4469            0 :         form.description = "ROC Retransmit Request Count Link 4";
    4470            0 :         std::stringstream o;
    4471            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_4, form.value);
    4472            0 :         form.vals.push_back(o.str());
    4473            0 :         return form;
    4474            0 : }
    4475              : 
    4476              : /// <summary>
    4477              : /// Formats the register's current value for register dumps
    4478              : /// </summary>
    4479              : /// <returns>RegisterFormatter object containing register information</returns>
    4480            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRetransmitRequestCountLink5()
    4481              : {
    4482            0 :         auto form = CreateFormatter(DTC_Register_RetransmitRequestCount_Link5);
    4483            0 :         form.description = "ROC Retransmit Request Count Link 5";
    4484            0 :         std::stringstream o;
    4485            0 :         o << std::dec << ReadRetransmitRequestCount(DTC_Link_5, form.value);
    4486            0 :         form.vals.push_back(o.str());
    4487            0 :         return form;
    4488            0 : }
    4489              : 
    4490              : // Missed CFO Packet Count Registers
    4491              : /**
    4492              :  * @brief Read the missed CFO Packet Count for the given link
    4493              :  * @param link Link to read
    4494              :  * @returns Number of missed CFO packets for the given link, or 0 if an invalid link is given
    4495              :  */
    4496            0 : uint32_t DTCLib::DTC_Registers::ReadMissedCFOPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    4497              : {
    4498            0 :         switch (link)
    4499              :         {
    4500            0 :                 case DTC_Link_0:
    4501            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link0);
    4502            0 :                 case DTC_Link_1:
    4503            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link1);
    4504            0 :                 case DTC_Link_2:
    4505            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link2);
    4506            0 :                 case DTC_Link_3:
    4507            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link3);
    4508            0 :                 case DTC_Link_4:
    4509            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link4);
    4510            0 :                 case DTC_Link_5:
    4511            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_MissedCFOPacketCount_Link5);
    4512            0 :                 default: {
    4513            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4514            0 :                         __SS_THROW__;
    4515            0 :                 }
    4516              :         }
    4517              : }
    4518              : 
    4519              : /// <summary>
    4520              : /// Clears the Missed CFO Packet Count for the given link
    4521              : /// </summary>
    4522              : /// <param name="link">Link to clear</param>
    4523            0 : void DTCLib::DTC_Registers::ClearMissedCFOPacketCount(DTC_Link_ID const& link)
    4524              : {
    4525            0 :         switch (link)
    4526              :         {
    4527            0 :                 case DTC_Link_0:
    4528            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link0);
    4529            0 :                         break;
    4530            0 :                 case DTC_Link_1:
    4531            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link1);
    4532            0 :                         break;
    4533            0 :                 case DTC_Link_2:
    4534            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link2);
    4535            0 :                         break;
    4536            0 :                 case DTC_Link_3:
    4537            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link3);
    4538            0 :                         break;
    4539            0 :                 case DTC_Link_4:
    4540            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link4);
    4541            0 :                         break;
    4542            0 :                 case DTC_Link_5:
    4543            0 :                         WriteRegister_(1, DTC_Register_MissedCFOPacketCount_Link5);
    4544            0 :                         break;
    4545            0 :                 default: {
    4546            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    4547            0 :                         __SS_THROW__;
    4548            0 :                 }
    4549              :         }
    4550            0 : }
    4551              : 
    4552              : /// <summary>
    4553              : /// Formats the register's current value for register dumps
    4554              : /// </summary>
    4555              : /// <returns>RegisterFormatter object containing register information</returns>
    4556            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink0()
    4557              : {
    4558            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link0);
    4559            0 :         form.description = "Missed CFO Packet Count Link 0";
    4560            0 :         std::stringstream o;
    4561            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_0, form.value);
    4562            0 :         form.vals.push_back(o.str());
    4563            0 :         return form;
    4564            0 : }
    4565              : 
    4566              : /// <summary>
    4567              : /// Formats the register's current value for register dumps
    4568              : /// </summary>
    4569              : /// <returns>RegisterFormatter object containing register information</returns>
    4570            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink1()
    4571              : {
    4572            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link1);
    4573            0 :         form.description = "Missed CFO Packet Count Link 1";
    4574            0 :         std::stringstream o;
    4575            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_1, form.value);
    4576            0 :         form.vals.push_back(o.str());
    4577            0 :         return form;
    4578            0 : }
    4579              : 
    4580              : /// <summary>
    4581              : /// Formats the register's current value for register dumps
    4582              : /// </summary>
    4583              : /// <returns>RegisterFormatter object containing register information</returns>
    4584            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink2()
    4585              : {
    4586            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link2);
    4587            0 :         form.description = "Missed CFO Packet Count Link 2";
    4588            0 :         std::stringstream o;
    4589            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_2, form.value);
    4590            0 :         form.vals.push_back(o.str());
    4591            0 :         return form;
    4592            0 : }
    4593              : 
    4594              : /// <summary>
    4595              : /// Formats the register's current value for register dumps
    4596              : /// </summary>
    4597              : /// <returns>RegisterFormatter object containing register information</returns>
    4598            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink3()
    4599              : {
    4600            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link3);
    4601            0 :         form.description = "Missed CFO Packet Count Link 3";
    4602            0 :         std::stringstream o;
    4603            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_3, form.value);
    4604            0 :         form.vals.push_back(o.str());
    4605            0 :         return form;
    4606            0 : }
    4607              : 
    4608              : /// <summary>
    4609              : /// Formats the register's current value for register dumps
    4610              : /// </summary>
    4611              : /// <returns>RegisterFormatter object containing register information</returns>
    4612            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink4()
    4613              : {
    4614            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link4);
    4615            0 :         form.description = "Missed CFO Packet Count Link 4";
    4616            0 :         std::stringstream o;
    4617            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_4, form.value);
    4618            0 :         form.vals.push_back(o.str());
    4619            0 :         return form;
    4620            0 : }
    4621              : 
    4622              : /// <summary>
    4623              : /// Formats the register's current value for register dumps
    4624              : /// </summary>
    4625              : /// <returns>RegisterFormatter object containing register information</returns>
    4626            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatMissedCFOPacketCountLink5()
    4627              : {
    4628            0 :         auto form = CreateFormatter(DTC_Register_MissedCFOPacketCount_Link5);
    4629            0 :         form.description = "Missed CFO Packet Count Link 5";
    4630            0 :         std::stringstream o;
    4631            0 :         o << std::dec << ReadMissedCFOPacketCount(DTC_Link_5, form.value);
    4632            0 :         form.vals.push_back(o.str());
    4633            0 :         return form;
    4634            0 : }
    4635              : 
    4636              : // Local Fragment Drop Count Register
    4637              : /// <summary>
    4638              : /// Reads the current value of the Local Fragment Drop Counter
    4639              : /// </summary>
    4640              : /// <returns>The number of fragments dropped by the DTC</returns>
    4641            0 : uint32_t DTCLib::DTC_Registers::ReadLocalFragmentDropCount(std::optional<uint32_t> val)
    4642              : {
    4643            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_LocalFragmentDropCount);
    4644              : }
    4645              : 
    4646              : /// <summary>
    4647              : /// Clears the Local Fragment Drop Counter
    4648              : /// </summary>
    4649            0 : void DTCLib::DTC_Registers::ClearLocalFragmentDropCount() { WriteRegister_(1, DTC_Register_LocalFragmentDropCount); }
    4650              : 
    4651              : /// <summary>
    4652              : /// Formats the register's current value for register dumps
    4653              : /// </summary>
    4654              : /// <returns>RegisterFormatter object containing register information</returns>
    4655            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLocalFragmentDropCount()
    4656              : {
    4657            0 :         auto form = CreateFormatter(DTC_Register_LocalFragmentDropCount);
    4658            0 :         form.description = "Local Data Fragment Drop Count";
    4659            0 :         std::stringstream o;
    4660            0 :         o << std::dec << ReadLocalFragmentDropCount(form.value);
    4661            0 :         form.vals.push_back(o.str());
    4662            0 :         return form;
    4663            0 : }
    4664              : 
    4665            0 : uint32_t DTCLib::DTC_Registers::ReadEVBSubEventReceiveTimer(std::optional<uint32_t> val)
    4666              : {
    4667            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSubEventReceiveTimerPreset);
    4668              : }
    4669              : 
    4670            0 : void DTCLib::DTC_Registers::SetEVBSubEventReceiveTimer(uint32_t timer)
    4671              : {
    4672            0 :         WriteRegister_(timer, DTC_Register_EVBSubEventReceiveTimerPreset);
    4673            0 : }
    4674              : 
    4675            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSubEventReceiveTimer()
    4676              : {
    4677            0 :         auto form = CreateFormatter(DTC_Register_EVBSubEventReceiveTimerPreset);
    4678            0 :         form.description = "EVB SubEvent Receive Timer (*4ns)";
    4679            0 :         std::stringstream o;
    4680            0 :         o << std::dec << ReadEVBSubEventReceiveTimer(form.value);
    4681            0 :         form.vals.push_back(o.str());
    4682            0 :         return form;
    4683            0 : }
    4684              : 
    4685              : // EVB SERDES PRBS Register
    4686              : /// <summary>
    4687              : /// Determine if an error was detected in the EVB SERDES PRBS module
    4688              : /// </summary>
    4689              : /// <returns>True if error condition was detected, false otherwise</returns>
    4690            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSErrorFlag(std::optional<uint32_t> val)
    4691              : {
    4692            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4693            0 :         return regVal[31];
    4694              : }
    4695              : 
    4696              : /// <summary>
    4697              : /// Read the EVB SERDES TX PRBS Select
    4698              : /// </summary>
    4699              : /// <returns>Value of the EVB SERDES TX PRBS Select</returns>
    4700            0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESTXPRBSSEL(std::optional<uint32_t> val)
    4701              : {
    4702            0 :         uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x7000) >> 12);
    4703            0 :         return regVal;
    4704              : }
    4705              : 
    4706              : /// <summary>
    4707              : /// Set the EVB SERDES TX PRBS Select
    4708              : /// </summary>
    4709              : /// <param name="byte">Value of the EVB SERDES TX PRBS Select</param>
    4710            0 : void DTCLib::DTC_Registers::SetEVBSERDESTXPRBSSEL(uint8_t byte)
    4711              : {
    4712            0 :         uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFF8FFF);
    4713            0 :         regVal += ((byte & 0x7) << 12);
    4714            0 :         WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
    4715            0 : }
    4716              : 
    4717              : /// <summary>
    4718              : /// Read the EVB SERDES RX PRBS Select
    4719              : /// </summary>
    4720              : /// <returns>Value of the EVB SERDES RX PRBS Select</returns>
    4721            0 : uint8_t DTCLib::DTC_Registers::ReadEVBSERDESRXPRBSSEL(std::optional<uint32_t> val)
    4722              : {
    4723            0 :         uint8_t regVal = static_cast<uint8_t>(((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus)) & 0x700) >> 8);
    4724            0 :         return regVal;
    4725              : }
    4726              : 
    4727              : /// <summary>
    4728              : /// Set the EVB SERDES RX PRBS Select
    4729              : /// </summary>
    4730              : /// <param name="byte">Value of the EVB SERDES RX PRBS Select</param>
    4731            0 : void DTCLib::DTC_Registers::SetEVBSERDESRXPRBSSEL(uint8_t byte)
    4732              : {
    4733            0 :         uint8_t regVal = (ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus) & 0xFFFFF8FF);
    4734            0 :         regVal += ((byte & 0x7) << 8);
    4735            0 :         WriteRegister_(regVal, DTC_Register_EVBSERDESPRBSControlStatus);
    4736            0 : }
    4737              : 
    4738              : /// <summary>
    4739              : /// Read the state of the EVB SERDES PRBS Force Error bit
    4740              : /// </summary>
    4741              : /// <returns>True if the EVB SERDES PRBS Force Error bit is high</returns>
    4742            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSForceError(std::optional<uint32_t> val)
    4743              : {
    4744            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4745            0 :         return regVal[1];
    4746              : }
    4747              : 
    4748              : /// <summary>
    4749              : /// Set the EVB SERDES PRBS Force Error bit
    4750              : /// </summary>
    4751              : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
    4752            0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSForceError(bool flag)
    4753              : {
    4754            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4755            0 :         regVal[1] = flag;
    4756            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4757            0 : }
    4758              : 
    4759              : /// <summary>
    4760              : /// Toggle the EVB SERDES PRBS Force Error bit (make it true if false, false if true)
    4761              : /// </summary>
    4762            0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSForceError()
    4763              : {
    4764            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4765            0 :         regVal.flip(0);
    4766            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4767            0 : }
    4768              : 
    4769              : /// <summary>
    4770              : /// Read the state of the EVB SERDES PRBS Reset bit
    4771              : /// </summary>
    4772              : /// <returns>True if the EVB SERDES PRBS Reset bit is high</returns>
    4773            0 : bool DTCLib::DTC_Registers::ReadEVBSERDESPRBSReset(std::optional<uint32_t> val)
    4774              : {
    4775            0 :         std::bitset<32> regVal(val.has_value() ? *val : ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4776            0 :         return regVal[0];
    4777              : }
    4778              : 
    4779              : /// <summary>
    4780              : /// Set the EVB SERDES PRBS Reset bit
    4781              : /// </summary>
    4782              : /// <param name="flag">New value for the EVB SERDES PRBS Reset bit</param>
    4783            0 : void DTCLib::DTC_Registers::SetEVBSERDESPRBSReset(bool flag)
    4784              : {
    4785            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4786            0 :         regVal[0] = flag;
    4787            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4788            0 : }
    4789              : 
    4790              : /// <summary>
    4791              : /// Toggle the EVB SERDES PRBS Reset bit (make it true if false, false if true)
    4792              : /// </summary>
    4793            0 : void DTCLib::DTC_Registers::ToggleEVBSERDESPRBSReset()
    4794              : {
    4795            0 :         std::bitset<32> regVal(ReadRegister_(DTC_Register_EVBSERDESPRBSControlStatus));
    4796            0 :         regVal.flip(0);
    4797            0 :         WriteRegister_(regVal.to_ulong(), DTC_Register_EVBSERDESPRBSControlStatus);
    4798            0 : }
    4799              : 
    4800              : /// <summary>
    4801              : /// Formats the register's current value for register dumps
    4802              : /// </summary>
    4803              : /// <returns>RegisterFormatter object containing register information</returns>
    4804            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESPRBSControl()
    4805              : {
    4806            0 :         auto form = CreateFormatter(DTC_Register_EVBSERDESPRBSControlStatus);
    4807            0 :         form.description = "EVB SERDES PRBS Control / Status";
    4808            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4809            0 :         form.vals.push_back(std::string("PRBS Error: [") + (ReadEVBSERDESPRBSErrorFlag(form.value) ? "x" : " ") + "]");
    4810            0 :         std::stringstream o;
    4811            0 :         o << "EVB SERDES TX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESTXPRBSSEL(form.value));
    4812            0 :         form.vals.push_back(o.str());
    4813            0 :         o.str("");
    4814            0 :         o.clear();
    4815            0 :         o << "EVB SERDES RX PRBS Select: 0x" << std::hex << static_cast<int>(ReadEVBSERDESRXPRBSSEL(form.value));
    4816            0 :         form.vals.push_back(std::string("PRBS Force Error: [") + (ReadEVBSERDESPRBSForceError(form.value) ? "x" : " ") + "]");
    4817            0 :         form.vals.push_back(std::string("PRBS Reset: [") + (ReadEVBSERDESPRBSReset(form.value) ? "x" : " ") + "]");
    4818              : 
    4819            0 :         return form;
    4820            0 : }
    4821              : 
    4822              : // Event Builder Error Register
    4823              : /// <summary>
    4824              : /// Read the Event Builder SubEvent Receiver Flags Buffer Error bit
    4825              : /// </summary>
    4826              : /// <returns>Value of the bit</returns>
    4827            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_SubEventReceiverFlagsBufferError(std::optional<uint32_t> val)
    4828              : {
    4829            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4830            0 :         return data[24];
    4831              : }
    4832              : /// <summary>
    4833              : /// Read the Event Builder Ethernet Input FIFO Full bit
    4834              : /// </summary>
    4835              : /// <returns>Value of the bit</returns>
    4836            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_EthernetInputFIFOFull(std::optional<uint32_t> val)
    4837              : {
    4838            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4839            0 :         return data[16];
    4840              : }
    4841              : /// <summary>
    4842              : /// Read the Event Builder Link Error bit
    4843              : /// </summary>
    4844              : /// <returns>Value of the bit</returns>
    4845            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LinkError(std::optional<uint32_t> val)
    4846              : {
    4847            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4848            0 :         return data[9];
    4849              : }
    4850              : /// <summary>
    4851              : /// Read the Event Builder TX Packet Error bit
    4852              : /// </summary>
    4853              : /// <returns>Value of the bit</returns>
    4854            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TXPacketError(std::optional<uint32_t> val)
    4855              : {
    4856            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4857            0 :         return data[8];
    4858              : }
    4859              : /// <summary>
    4860              : /// Read the Event Builder Local Data Pointer FIFO Queue Error bit
    4861              : /// </summary>
    4862              : /// <returns>Value of the bit</returns>
    4863            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_LocalDataPointerFIFOQueueError(std::optional<uint32_t> val)
    4864              : {
    4865            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4866            0 :         return data[1];
    4867              : }
    4868              : /// <summary>
    4869              : /// Read the Event Builder Transmit DMA Byte Count FIFO Full bit
    4870              : /// </summary>
    4871              : /// <returns>Value of the bit</returns>
    4872            0 : bool DTCLib::DTC_Registers::ReadEventBuilder_TransmitDMAByteCountFIFOFull(std::optional<uint32_t> val)
    4873              : {
    4874            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_EventBuilderErrorFlags);
    4875            0 :         return data[0];
    4876              : }
    4877              : /// <summary>
    4878              : /// Formats the register's current value for register dumps
    4879              : /// </summary>
    4880              : /// <returns>RegisterFormatter object containing register information</returns>
    4881            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEventBuilderErrorRegister()
    4882              : {
    4883            0 :         auto form = CreateFormatter(DTC_Register_EventBuilderErrorFlags);
    4884            0 :         form.description = "EVB Errors / Status";
    4885            0 :         form.vals = DecodeEVBErrorStatus(form.value);
    4886            0 :         return form;
    4887            0 : }
    4888              : 
    4889              : // SERDES VFIFO Error Register
    4890              : /// <summary>
    4891              : /// Read the SERDES VFIFO Egress FIFO Full bit
    4892              : /// </summary>
    4893              : /// <returns>Value of the bit</returns>
    4894            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
    4895              : {
    4896            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4897            0 :         return data[10];
    4898              : }
    4899              : /// <summary>
    4900              : /// Read the SERDES VFIFO Ingress FIFO Full bit
    4901              : /// </summary>
    4902              : /// <returns>Value of the bit</returns>
    4903            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
    4904              : {
    4905            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4906            0 :         return data[9];
    4907              : }
    4908              : /// <summary>
    4909              : /// Read the SERDES VFIFO Event Byte Count Total Error bit
    4910              : /// </summary>
    4911              : /// <returns>Value of the bit</returns>
    4912            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
    4913              : {
    4914            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4915            0 :         return data[8];
    4916              : }
    4917              : /// <summary>
    4918              : /// Read the SERDES VFIFO Last Word Written Timeout Error bit
    4919              : /// </summary>
    4920              : /// <returns>Value of the bit</returns>
    4921            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_LastWordWrittenTimeoutError(std::optional<uint32_t> val)
    4922              : {
    4923            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4924            0 :         return data[2];
    4925              : }
    4926              : /// <summary>
    4927              : /// Read the SERDES VFIFO Fragment Count Error bit
    4928              : /// </summary>
    4929              : /// <returns>Value of the bit</returns>
    4930            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_FragmentCountError(std::optional<uint32_t> val)
    4931              : {
    4932            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4933            0 :         return data[1];
    4934              : }
    4935              : /// <summary>
    4936              : /// Read the SERDES VFIFO DDR Full Error bit
    4937              : /// </summary>
    4938              : /// <returns>Value of the bit</returns>
    4939            0 : bool DTCLib::DTC_Registers::ReadSERDESVFIFO_DDRFullError(std::optional<uint32_t> val)
    4940              : {
    4941            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferErrorFlags);
    4942            0 :         return data[0];
    4943              : }
    4944              : /// <summary>
    4945              : /// Formats the register's current value for register dumps
    4946              : /// </summary>
    4947              : /// <returns>RegisterFormatter object containing register information</returns>
    4948            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESVFIFOError()
    4949              : {
    4950            0 :         auto form = CreateFormatter(DTC_Register_InputBufferErrorFlags);
    4951            0 :         form.description = "SERDES VFIFO Error Flags";
    4952            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    4953            0 :         form.vals.push_back(std::string("Egress FIFO Full:             [") + (ReadSERDESVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
    4954              :                                                 "]");
    4955            0 :         form.vals.push_back(std::string("Ingress FIFO Full:            [") + (ReadSERDESVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
    4956              :                                                 "]");
    4957            0 :         form.vals.push_back(std::string("Event Byte Count Total Error: [") +
    4958            0 :                                                 (ReadSERDESVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
    4959            0 :         form.vals.push_back(std::string("Last Word Written Timeout:    [") +
    4960            0 :                                                 (ReadSERDESVFIFO_LastWordWrittenTimeoutError(form.value) ? "x" : " ") + "]");
    4961            0 :         form.vals.push_back(std::string("Fragment count Error:         [") +
    4962            0 :                                                 (ReadSERDESVFIFO_FragmentCountError(form.value) ? "x" : " ") + "]");
    4963            0 :         form.vals.push_back(std::string("DDR Full Error:               [") + (ReadSERDESVFIFO_DDRFullError(form.value) ? "x" : " ") +
    4964              :                                                 "]");
    4965            0 :         return form;
    4966            0 : }
    4967              : 
    4968              : // PCI VFIFO Error Register
    4969              : /// <summary>
    4970              : /// Read the PCI VIFO DDR Full bit
    4971              : /// </summary>
    4972              : /// <returns>Value of the bit</returns>
    4973            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_DDRFull(std::optional<uint32_t> val)
    4974              : {
    4975            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4976            0 :         return data[12];
    4977              : }
    4978              : /// <summary>
    4979              : /// Read the PCI VIFO Memmory Mapped Write Complete FIFO Full bit
    4980              : /// </summary>
    4981              : /// <returns>Value of the bit</returns>
    4982            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(std::optional<uint32_t> val)
    4983              : {
    4984            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4985            0 :         return data[11];
    4986              : }
    4987              : /// <summary>
    4988              : /// Read the PCI VIFO PCI Write Event FIFO Full bit
    4989              : /// </summary>
    4990              : /// <returns>Value of the bit</returns>
    4991            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_PCIWriteEventFIFOFull(std::optional<uint32_t> val)
    4992              : {
    4993            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    4994            0 :         return data[10];
    4995              : }
    4996              : /// <summary>
    4997              : /// Read the PCI VIFO Local Data Pointer FIFO Full bit
    4998              : /// </summary>
    4999              : /// <returns>Value of the bit</returns>
    5000            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_LocalDataPointerFIFOFull(std::optional<uint32_t> val)
    5001              : {
    5002            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    5003            0 :         return data[9];
    5004              : }
    5005              : /// <summary>
    5006              : /// Read the PCI VIFO Egress FIFO Full bit
    5007              : /// </summary>
    5008              : /// <returns>Value of the bit</returns>
    5009            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EgressFIFOFull(std::optional<uint32_t> val)
    5010              : {
    5011            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    5012            0 :         return data[8];
    5013              : }
    5014              : /// <summary>
    5015              : /// Read the PCI VIFO RX Buffer Select FIFO Full bit
    5016              : /// </summary>
    5017              : /// <returns>Value of the bit</returns>
    5018            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_RXBufferSelectFIFOFull(std::optional<uint32_t> val)
    5019              : {
    5020            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    5021            0 :         return data[2];
    5022              : }
    5023              : /// <summary>
    5024              : /// Read the PCI VIFO Ingress FIFO Full bit
    5025              : /// </summary>
    5026              : /// <returns>Value of the bit</returns>
    5027            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_IngressFIFOFull(std::optional<uint32_t> val)
    5028              : {
    5029            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    5030            0 :         return data[1];
    5031              : }
    5032              : /// <summary>
    5033              : /// Read the PCI VIFO Event Byte Count Total Error bit
    5034              : /// </summary>
    5035              : /// <returns>Value of the bit</returns>
    5036            0 : bool DTCLib::DTC_Registers::ReadPCIVFIFO_EventByteCountTotalError(std::optional<uint32_t> val)
    5037              : {
    5038            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferErrorFlags);
    5039            0 :         return data[0];
    5040              : }
    5041              : /// <summary>
    5042              : /// Formats the register's current value for register dumps
    5043              : /// </summary>
    5044              : /// <returns>RegisterFormatter object containing register information</returns>
    5045            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatPCIVFIFOError()
    5046              : {
    5047            0 :         auto form = CreateFormatter(DTC_Register_OutputBufferErrorFlags);
    5048            0 :         form.description = "PCI VFIFO Error Flags";
    5049            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5050            0 :         form.vals.push_back(std::string("DDR Full Error:               [") + (ReadPCIVFIFO_DDRFull(form.value) ? "x" : " ") + "]");
    5051            0 :         form.vals.push_back(std::string("Memmap Write Cmplt FIFO Full: [") +
    5052            0 :                                                 (ReadPCIVFIFO_MemoryMappedWriteCompleteFIFOFull(form.value) ? "x" : " ") + "]");
    5053            0 :         form.vals.push_back(std::string("PCI Write Event FIFO Full:    [") +
    5054            0 :                                                 (ReadPCIVFIFO_PCIWriteEventFIFOFull(form.value) ? "x" : " ") + "]");
    5055            0 :         form.vals.push_back(std::string("Local Data Pointer FIFO Full: [") +
    5056            0 :                                                 (ReadPCIVFIFO_LocalDataPointerFIFOFull(form.value) ? "x" : " ") + "]");
    5057            0 :         form.vals.push_back(std::string("Egress FIFO Full:             [") + (ReadPCIVFIFO_EgressFIFOFull(form.value) ? "x" : " ") +
    5058              :                                                 "]");
    5059            0 :         form.vals.push_back(std::string("RX Buffer Select FIFO Full:   [") +
    5060            0 :                                                 (ReadPCIVFIFO_RXBufferSelectFIFOFull(form.value) ? "x" : " ") + "]");
    5061            0 :         form.vals.push_back(std::string("Ingress FIFO Ful:             [") + (ReadPCIVFIFO_IngressFIFOFull(form.value) ? "x" : " ") +
    5062              :                                                 "]");
    5063            0 :         form.vals.push_back(std::string("Event Byte Count Total Error: [") +
    5064            0 :                                                 (ReadPCIVFIFO_EventByteCountTotalError(form.value) ? "x" : " ") + "]");
    5065            0 :         return form;
    5066            0 : }
    5067              : 
    5068              : // ROC Link Error Registers
    5069              : /// <summary>
    5070              : /// Read the Receive Data Request Sync Error bit for the given link
    5071              : /// </summary>
    5072              : /// <param name="link">Link to read</param>
    5073              : /// <returns>Value of the bit</returns>
    5074            0 : bool DTCLib::DTC_Registers::ReadROCLink_ROCDataRequestSyncError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5075              : {
    5076            0 :         std::bitset<32> data;
    5077            0 :         switch (link)
    5078              :         {
    5079            0 :                 case DTC_Link_0:
    5080            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5081            0 :                         break;
    5082            0 :                 case DTC_Link_1:
    5083            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5084            0 :                         break;
    5085            0 :                 case DTC_Link_2:
    5086            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5087            0 :                         break;
    5088            0 :                 case DTC_Link_3:
    5089            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5090            0 :                         break;
    5091            0 :                 case DTC_Link_4:
    5092            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5093            0 :                         break;
    5094            0 :                 case DTC_Link_5:
    5095            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5096            0 :                         break;
    5097            0 :                 default: {
    5098            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5099            0 :                         __SS_THROW__;
    5100            0 :                 }
    5101              :         }
    5102            0 :         return data[5];
    5103              : }
    5104              : /// <summary>
    5105              : /// Read the Receive RX Packet Count Error bit for the given link
    5106              : /// </summary>
    5107              : /// <param name="link">Link to read</param>
    5108              : /// <returns>Value of the bit</returns>
    5109            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5110              : {
    5111            0 :         std::bitset<32> data;
    5112            0 :         switch (link)
    5113              :         {
    5114            0 :                 case DTC_Link_0:
    5115            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5116            0 :                         break;
    5117            0 :                 case DTC_Link_1:
    5118            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5119            0 :                         break;
    5120            0 :                 case DTC_Link_2:
    5121            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5122            0 :                         break;
    5123            0 :                 case DTC_Link_3:
    5124            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5125            0 :                         break;
    5126            0 :                 case DTC_Link_4:
    5127            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5128            0 :                         break;
    5129            0 :                 case DTC_Link_5:
    5130            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5131            0 :                         break;
    5132            0 :                 default: {
    5133            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5134            0 :                         __SS_THROW__;
    5135            0 :                 }
    5136              :         }
    5137            0 :         return data[4];
    5138              : }
    5139              : /// <summary>
    5140              : /// Read the Receive RX Packet Error bit for the given link
    5141              : /// </summary>
    5142              : /// <param name="link">Link to read</param>
    5143              : /// <returns>Value of the bit</returns>
    5144            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5145              : {
    5146            0 :         std::bitset<32> data;
    5147            0 :         switch (link)
    5148              :         {
    5149            0 :                 case DTC_Link_0:
    5150            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5151            0 :                         break;
    5152            0 :                 case DTC_Link_1:
    5153            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5154            0 :                         break;
    5155            0 :                 case DTC_Link_2:
    5156            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5157            0 :                         break;
    5158            0 :                 case DTC_Link_3:
    5159            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5160            0 :                         break;
    5161            0 :                 case DTC_Link_4:
    5162            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5163            0 :                         break;
    5164            0 :                 case DTC_Link_5:
    5165            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5166            0 :                         break;
    5167            0 :                 default: {
    5168            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5169            0 :                         __SS_THROW__;
    5170            0 :                 }
    5171              :         }
    5172            0 :         return data[3];
    5173              : }
    5174              : /// <summary>
    5175              : /// Read the Receive RX Packet CRC Error bit for the given link
    5176              : /// </summary>
    5177              : /// <param name="link">Link to read</param>
    5178              : /// <returns>Value of the bit</returns>
    5179            0 : bool DTCLib::DTC_Registers::ReadROCLink_RXPacketCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5180              : {
    5181            0 :         std::bitset<32> data;
    5182            0 :         switch (link)
    5183              :         {
    5184            0 :                 case DTC_Link_0:
    5185            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5186            0 :                         break;
    5187            0 :                 case DTC_Link_1:
    5188            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5189            0 :                         break;
    5190            0 :                 case DTC_Link_2:
    5191            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5192            0 :                         break;
    5193            0 :                 case DTC_Link_3:
    5194            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5195            0 :                         break;
    5196            0 :                 case DTC_Link_4:
    5197            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5198            0 :                         break;
    5199            0 :                 case DTC_Link_5:
    5200            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5201            0 :                         break;
    5202            0 :                 default: {
    5203            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5204            0 :                         __SS_THROW__;
    5205            0 :                 }
    5206              :         }
    5207            0 :         return data[2];
    5208              : }
    5209              : /// <summary>
    5210              : /// Read the Receive Data Pending Timeout Error bit for the given link
    5211              : /// </summary>
    5212              : /// <param name="link">Link to read</param>
    5213              : /// <returns>Value of the bit</returns>
    5214            0 : bool DTCLib::DTC_Registers::ReadROCLink_DataPendingTimeoutError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5215              : {
    5216            0 :         std::bitset<32> data;
    5217            0 :         switch (link)
    5218              :         {
    5219            0 :                 case DTC_Link_0:
    5220            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5221            0 :                         break;
    5222            0 :                 case DTC_Link_1:
    5223            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5224            0 :                         break;
    5225            0 :                 case DTC_Link_2:
    5226            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5227            0 :                         break;
    5228            0 :                 case DTC_Link_3:
    5229            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5230            0 :                         break;
    5231            0 :                 case DTC_Link_4:
    5232            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5233            0 :                         break;
    5234            0 :                 case DTC_Link_5:
    5235            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5236            0 :                         break;
    5237            0 :                 default: {
    5238            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5239            0 :                         __SS_THROW__;
    5240            0 :                 }
    5241              :         }
    5242            0 :         return data[1];
    5243              : }
    5244              : /// <summary>
    5245              : /// Read the Receive Data Packet Count Error bit for the given link
    5246              : /// </summary>
    5247              : /// <param name="link">Link to read</param>
    5248              : /// <returns>Value of the bit</returns>
    5249            0 : bool DTCLib::DTC_Registers::ReadROCLink_ReceiveDataPacketCountError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5250              : {
    5251            0 :         std::bitset<32> data;
    5252            0 :         switch (link)
    5253              :         {
    5254            0 :                 case DTC_Link_0:
    5255            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link0ErrorFlags);
    5256            0 :                         break;
    5257            0 :                 case DTC_Link_1:
    5258            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link1ErrorFlags);
    5259            0 :                         break;
    5260            0 :                 case DTC_Link_2:
    5261            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link2ErrorFlags);
    5262            0 :                         break;
    5263            0 :                 case DTC_Link_3:
    5264            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link3ErrorFlags);
    5265            0 :                         break;
    5266            0 :                 case DTC_Link_4:
    5267            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link4ErrorFlags);
    5268            0 :                         break;
    5269            0 :                 case DTC_Link_5:
    5270            0 :                         data = val.has_value() ? *val : ReadRegister_(DTC_Register_Link5ErrorFlags);
    5271            0 :                         break;
    5272            0 :                 default: {
    5273            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5274            0 :                         __SS_THROW__;
    5275            0 :                 }
    5276              :         }
    5277            0 :         return data[0];
    5278              : }
    5279              : /// <summary>
    5280              : /// Formats the register's current value for register dumps
    5281              : /// </summary>
    5282              : /// <returns>RegisterFormatter object containing register information</returns>
    5283            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink0Error()
    5284              : {
    5285            0 :         auto form = CreateFormatter(DTC_Register_Link0ErrorFlags);
    5286            0 :         form.description = "ROC Link 0 Error";
    5287            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5288            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5289            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5290            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5291            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5292            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5293            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5294            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5295            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5296            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5297            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5298            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5299            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_0, form.value) ? "x" : " ") + "]");
    5300            0 :         return form;
    5301            0 : }
    5302              : /// <summary>
    5303              : /// Formats the register's current value for register dumps
    5304              : /// </summary>
    5305              : /// <returns>RegisterFormatter object containing register information</returns>
    5306            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink1Error()
    5307              : {
    5308            0 :         auto form = CreateFormatter(DTC_Register_Link1ErrorFlags);
    5309            0 :         form.description = "ROC Link 1 Error";
    5310            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5311            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5312            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5313            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5314            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5315            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5316            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5317            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5318            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5319            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5320            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5321            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5322            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_1, form.value) ? "x" : " ") + "]");
    5323            0 :         return form;
    5324            0 : }
    5325              : /// <summary>
    5326              : /// Formats the register's current value for register dumps
    5327              : /// </summary>
    5328              : /// <returns>RegisterFormatter object containing register information</returns>
    5329            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink2Error()
    5330              : {
    5331            0 :         auto form = CreateFormatter(DTC_Register_Link2ErrorFlags);
    5332            0 :         form.description = "ROC Link 2 Error";
    5333            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5334            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5335            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5336            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5337            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5338            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5339            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5340            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5341            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5342            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5343            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5344            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5345            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_2, form.value) ? "x" : " ") + "]");
    5346            0 :         return form;
    5347            0 : }
    5348              : /// <summary>
    5349              : /// Formats the register's current value for register dumps
    5350              : /// </summary>
    5351              : /// <returns>RegisterFormatter object containing register information</returns>
    5352            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink3Error()
    5353              : {
    5354            0 :         auto form = CreateFormatter(DTC_Register_Link3ErrorFlags);
    5355            0 :         form.description = "ROC Link 3 Error";
    5356            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5357            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5358            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5359            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5360            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5361            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5362            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5363            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5364            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5365            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5366            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5367            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5368            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_3, form.value) ? "x" : " ") + "]");
    5369            0 :         return form;
    5370            0 : }
    5371              : /// <summary>
    5372              : /// Formats the register's current value for register dumps
    5373              : /// </summary>
    5374              : /// <returns>RegisterFormatter object containing register information</returns>
    5375            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink4Error()
    5376              : {
    5377            0 :         auto form = CreateFormatter(DTC_Register_Link4ErrorFlags);
    5378            0 :         form.description = "ROC Link 4 Error";
    5379            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5380            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5381            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5382            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5383            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5384            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5385            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5386            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5387            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5388            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5389            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5390            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5391            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_4, form.value) ? "x" : " ") + "]");
    5392            0 :         return form;
    5393            0 : }
    5394              : /// <summary>
    5395              : /// Formats the register's current value for register dumps
    5396              : /// </summary>
    5397              : /// <returns>RegisterFormatter object containing register information</returns>
    5398            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRocLink5Error()
    5399              : {
    5400            0 :         auto form = CreateFormatter(DTC_Register_Link5ErrorFlags);
    5401            0 :         form.description = "ROC Link 5 Error";
    5402            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5403            0 :         form.vals.push_back(std::string("ROC Data Request Sync Error:     [") +
    5404            0 :                                                 (ReadROCLink_ROCDataRequestSyncError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5405            0 :         form.vals.push_back(std::string("RX Packet Count Error:           [") +
    5406            0 :                                                 (ReadROCLink_RXPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5407            0 :         form.vals.push_back(std::string("RX Packet Error:                 [") +
    5408            0 :                                                 (ReadROCLink_RXPacketError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5409            0 :         form.vals.push_back(std::string("RX Packet CRC Error:             [") +
    5410            0 :                                                 (ReadROCLink_RXPacketCRCError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5411            0 :         form.vals.push_back(std::string("Data Pending Timeout Error:      [") +
    5412            0 :                                                 (ReadROCLink_DataPendingTimeoutError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5413            0 :         form.vals.push_back(std::string("Receive Data Packet Count Error: [") +
    5414            0 :                                                 (ReadROCLink_ReceiveDataPacketCountError(DTC_Link_5, form.value) ? "x" : " ") + "]");
    5415            0 :         return form;
    5416            0 : }
    5417              : 
    5418              : // CFO Link Error Register
    5419              : /// <summary>
    5420              : /// Formats the register's current value for register dumps
    5421              : /// </summary>
    5422              : /// <returns>RegisterFormatter object containing register information</returns>
    5423            0 : uint32_t DTCLib::DTC_Registers::ReadCFOLinkErrorRegister()
    5424              : {
    5425            0 :         return ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5426              : }  // end ReadCFOLinkErrorRegister()
    5427              : 
    5428              : /// @brief Measured CFO marker sample position at bits [18:16]
    5429            0 : int DTCLib::DTC_Registers::ReadCFOMeasuredMarkerPosition(std::optional<uint32_t> val)
    5430              : {
    5431            0 :         uint32_t value = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5432            0 :         return (value >> 16) & 7;
    5433              : }  // end ReadCFOMeasuredMarkerPosition()
    5434              : 
    5435              : /// @brief Implied CFO sample offset for the measured marker position.
    5436              : ///        Legal values are -2 -1 0 1 2 (if measured value is 4 3 2 1 0, respectively).
    5437            0 : int DTCLib::DTC_Registers::ReadCFOImpliedMarkerOffset(std::optional<uint32_t> val)
    5438              : {
    5439            0 :         return 2 - ReadCFOMeasuredMarkerPosition(val);
    5440              : }  // end ReadCFOImpliedMarkerOffset()
    5441              : 
    5442              : /// @brief bit 9 - Event Start marker tx error at CFO Interface
    5443            0 : bool DTCLib::DTC_Registers::ReadCFOEventStartMarkerTxError(std::optional<uint32_t> val)
    5444              : {
    5445            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5446            0 :         return data[9];
    5447              : }  // end ReadCFOEventStartMarkerTxError()
    5448              : 
    5449              : /// @brief bit 10 - Clock marker tx error at CFO Interface
    5450            0 : bool DTCLib::DTC_Registers::ReadCFOClockMarkerTxError(std::optional<uint32_t> val)
    5451              : {
    5452            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5453            0 :         return data[10];
    5454              : }  // end ReadCFOClockMarkerTxError()
    5455              : 
    5456              : /// @brief bit 11 - RTF 40MHz clock phase has shifted
    5457            0 : bool DTCLib::DTC_Registers::ReadCFORTF40MHzPhaseShiftError(std::optional<uint32_t> val)
    5458              : {
    5459            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5460            0 :         return data[11];
    5461              : }  // end ReadCFORTF40MHzPhaseShiftError()
    5462              : 
    5463              : /// @brief bit 12 - Illegal marker timing in RTF 40MHz clock count
    5464            0 : bool DTCLib::DTC_Registers::ReadCFOIllegalMarkerTimingError(std::optional<uint32_t> val)
    5465              : {
    5466            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5467            0 :         return data[12];
    5468              : }  // end ReadCFOIllegalMarkerTimingError()
    5469              : 
    5470              : /// @brief bit 13 - Moving data from CFO rx to tx clock domain has marker corruption at "external" CFO Interface
    5471            0 : bool DTCLib::DTC_Registers::ReadCFORxToTxDataCorruptionError(std::optional<uint32_t> val)
    5472              : {
    5473            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkErrorFlags);
    5474            0 :         return data[13];
    5475              : }  // end ReadCFORxToTxDataCorruptionError()
    5476              : 
    5477            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOLinkError()
    5478              : {
    5479            0 :         auto form = CreateFormatter(DTC_Register_CFOLinkErrorFlags);
    5480            0 :         form.description = "CFO Link Settings & Error Flags";
    5481            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5482              : 
    5483            0 :         form.vals.push_back(std::string("CFO Event Start Marker tx Error:     [") +
    5484            0 :                                                 (ReadCFOEventStartMarkerTxError(form.value) ? "x" : " ") + "]");
    5485            0 :         form.vals.push_back(std::string("CFO Clock Marker tx Error:           [") +
    5486            0 :                                                 (ReadCFOClockMarkerTxError(form.value) ? "x" : " ") + "]");
    5487            0 :         form.vals.push_back(std::string("CFO RTF 40MHz Phase Shift Error:     [") +
    5488            0 :                                                 (ReadCFORTF40MHzPhaseShiftError(form.value) ? "x" : " ") + "]");
    5489            0 :         form.vals.push_back(std::string("CFO Illegal Marker Over Link Timing: [") +
    5490            0 :                                                 (ReadCFOIllegalMarkerTimingError(form.value) ? "x" : " ") + "]");
    5491            0 :         form.vals.push_back(std::string("CFO Rx-to-Tx Data Corruption Error:  [") +
    5492            0 :                                                 (ReadCFORxToTxDataCorruptionError(form.value) ? "x" : " ") + "]");
    5493            0 :         int measuredPos = ReadCFOMeasuredMarkerPosition(form.value);
    5494            0 :         int impliedPos = ReadCFOImpliedMarkerOffset(form.value);  // legal values are -2 -1 0 1 2 (if measured value is 4 3 2 1 0, respectively)
    5495            0 :         form.vals.push_back(std::string("CFO Measured Marker position {0,4}:  [") +
    5496            0 :                                                 std::to_string(measuredPos) + "] ==> " + std::to_string(impliedPos));
    5497            0 :         form.vals.push_back(std::string("CFO Permanent Offset setting {-2,2}: [") +
    5498            0 :                                                 std::to_string(ReadCFOSamplePermanentOffset(form.value)) + "]");
    5499              : 
    5500            0 :         form.vals.push_back("");  // spacer
    5501              : 
    5502              :         // also show link enables for CFO and EVB
    5503            0 :         uint32_t val = ReadRegister_(CFOandDTC_Register_LinkEnable);
    5504            0 :         form.vals.push_back(std::string("CFO Link Rx Enabled:                 [") +
    5505            0 :                                                 (ReadLinkEnabled(DTC_Link_CFO, val).ReceiveEnable ? "x" : " ") + "]");
    5506            0 :         form.vals.push_back(std::string("CFO Link Tx Enabled:                 [") +
    5507            0 :                                                 (ReadLinkEnabled(DTC_Link_CFO, val).TransmitEnable ? "x" : " ") + "]");
    5508            0 :         form.vals.push_back(std::string("EVB Link Rx Enabled:                 [") +
    5509            0 :                                                 (ReadLinkEnabled(DTC_Link_EVB, val).ReceiveEnable ? "x" : " ") + "]");
    5510            0 :         form.vals.push_back(std::string("EVB Link Tx Enabled:                 [") +
    5511            0 :                                                 (ReadLinkEnabled(DTC_Link_EVB, val).TransmitEnable ? "x" : " ") + "]");
    5512              : 
    5513            0 :         return form;
    5514            0 : }
    5515              : 
    5516              : // Link Mux Error Register
    5517              : /// <summary>
    5518              : /// Read the DCS Mux Decode Error bit
    5519              : /// </summary>
    5520              : /// <returns>Value of the bit</returns>
    5521            0 : bool DTCLib::DTC_Registers::ReadDCSMuxDecodeError(std::optional<uint32_t> val)
    5522              : {
    5523            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
    5524            0 :         return data[1];
    5525              : }
    5526              : /// <summary>
    5527              : /// Read the Data Mux Decode Error bit
    5528              : /// </summary>
    5529              : /// <returns>Value of the bit</returns>
    5530            0 : bool DTCLib::DTC_Registers::ReadDataMuxDecodeError(std::optional<uint32_t> val)
    5531              : {
    5532            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_LinkMuxErrorFlags);
    5533            0 :         return data[0];
    5534              : }
    5535              : /// <summary>
    5536              : /// Formats the register's current value for register dumps
    5537              : /// </summary>
    5538              : /// <returns>RegisterFormatter object containing register information</returns>
    5539            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatLinkMuxError()
    5540              : {
    5541            0 :         auto form = CreateFormatter(DTC_Register_LinkMuxErrorFlags);
    5542            0 :         form.description = "Link Mux Error Flags";
    5543            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5544            0 :         form.vals.push_back(std::string("DCS Mux Decode Error:  [") + (ReadDCSMuxDecodeError(form.value) ? "x" : " ") + "]");
    5545            0 :         form.vals.push_back(std::string("Data Mux Decode Error: [") + (ReadDataMuxDecodeError(form.value) ? "x" : " ") + "]");
    5546            0 :         return form;
    5547            0 : }
    5548              : 
    5549              : // SFP Control/Status Register
    5550              : /// <summary>
    5551              : /// Read the SFP Present bit
    5552              : /// </summary>
    5553              : /// <returns>Value of the bit</returns>
    5554            0 : bool DTCLib::DTC_Registers::ReadSFPPresent(std::optional<uint32_t> val)
    5555              : {
    5556            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5557            0 :         return data[31];
    5558              : }
    5559              : 
    5560              : /// <summary>
    5561              : /// Read the SFP LOS bit
    5562              : /// </summary>
    5563              : /// <returns>Value of the bit</returns>
    5564            0 : bool DTCLib::DTC_Registers::ReadSFPLOS(std::optional<uint32_t> val)
    5565              : {
    5566            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5567            0 :         return data[17];
    5568              : }
    5569              : 
    5570              : /// <summary>
    5571              : /// Read the SFP TX Fault bit
    5572              : /// </summary>
    5573              : /// <returns>Value of the bit</returns>
    5574            0 : bool DTCLib::DTC_Registers::ReadSFPTXFault(std::optional<uint32_t> val)
    5575              : {
    5576            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5577            0 :         return data[16];
    5578              : }
    5579              : 
    5580              : /// <summary>
    5581              : /// Set the SFP Rate Select bit high
    5582              : /// </summary>
    5583            0 : void DTCLib::DTC_Registers::EnableSFPRateSelect()
    5584              : {
    5585            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5586            0 :         data[1] = 1;
    5587            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5588            0 : }
    5589              : 
    5590              : /// <summary>
    5591              : /// Set the SFP Rate Select bit low
    5592              : /// </summary>
    5593            0 : void DTCLib::DTC_Registers::DisableSFPRateSelect()
    5594              : {
    5595            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5596            0 :         data[1] = 0;
    5597            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5598            0 : }
    5599              : 
    5600              : /// <summary>
    5601              : /// Read the value of the SFP Rate Select bit
    5602              : /// </summary>
    5603              : /// <returns>The value of the SFP Rate Select bit</returns>
    5604            0 : bool DTCLib::DTC_Registers::ReadSFPRateSelect(std::optional<uint32_t> val)
    5605              : {
    5606            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5607            0 :         return data[1];
    5608              : }
    5609              : 
    5610              : /// <summary>
    5611              : /// Disable SFP TX
    5612              : /// </summary>
    5613            0 : void DTCLib::DTC_Registers::DisableSFPTX()
    5614              : {
    5615            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5616            0 :         data[0] = 1;
    5617            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5618            0 : }
    5619              : 
    5620              : /// <summary>
    5621              : /// Enable SFP TX
    5622              : /// </summary>
    5623            0 : void DTCLib::DTC_Registers::EnableSFPTX()
    5624              : {
    5625            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SFPControlStatus);
    5626            0 :         data[0] = 0;
    5627            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SFPControlStatus);
    5628            0 : }
    5629              : 
    5630              : /// <summary>
    5631              : /// Read the SFP TX Disable bit
    5632              : /// </summary>
    5633              : /// <returns>Value of the SFP TX Disable bit</returns>
    5634            0 : bool DTCLib::DTC_Registers::ReadSFPTXDisable(std::optional<uint32_t> val)
    5635              : {
    5636            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SFPControlStatus);
    5637            0 :         return data[0];
    5638              : }
    5639              : 
    5640              : /// <summary>
    5641              : /// Formats the register's current value for register dumps
    5642              : /// </summary>
    5643              : /// <returns>RegisterFormatter object containing register information</returns>
    5644            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSFPControlStatus()
    5645              : {
    5646            0 :         auto form = CreateFormatter(DTC_Register_SFPControlStatus);
    5647            0 :         form.description = "SFP Control Status";
    5648            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5649            0 :         form.vals.push_back(std::string("SFP Present:     [") + (ReadSFPPresent(form.value) ? "x" : " ") + "]");
    5650            0 :         form.vals.push_back(std::string("SFP LOS:         [") + (ReadSFPLOS(form.value) ? "x" : " ") + "]");
    5651            0 :         form.vals.push_back(std::string("SFP TX Fault:    [") + (ReadSFPTXFault(form.value) ? "x" : " ") + "]");
    5652            0 :         form.vals.push_back(std::string("SFP Rate Select: [") + (ReadSFPRateSelect(form.value) ? "x" : " ") + "]");
    5653            0 :         form.vals.push_back(std::string("SFP TX Disable:  [") + (ReadSFPTXDisable(form.value) ? "x" : " ") + "]");
    5654            0 :         return form;
    5655            0 : }
    5656              : 
    5657            0 : uint32_t DTCLib::DTC_Registers::ReadRXCDRUnlockCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    5658              : {
    5659            0 :         switch (link)
    5660              :         {
    5661            0 :                 case DTC_Link_0:
    5662            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link0);
    5663            0 :                 case DTC_Link_1:
    5664            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link1);
    5665            0 :                 case DTC_Link_2:
    5666            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link2);
    5667            0 :                 case DTC_Link_3:
    5668            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link3);
    5669            0 :                 case DTC_Link_4:
    5670            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link4);
    5671            0 :                 case DTC_Link_5:
    5672            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_Link5);
    5673            0 :                 case DTC_Link_CFO:
    5674            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_RXCDRUnlockCount_CFOLink);
    5675            0 :                 default: {
    5676            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5677            0 :                         __SS_THROW__;
    5678            0 :                 }
    5679              :         }
    5680              : }
    5681              : 
    5682            0 : void DTCLib::DTC_Registers::ClearRXCDRUnlockCount(DTC_Link_ID const& link)
    5683              : {
    5684            0 :         switch (link)
    5685              :         {
    5686            0 :                 case DTC_Link_0:
    5687            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link0);
    5688            0 :                         break;
    5689            0 :                 case DTC_Link_1:
    5690            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link1);
    5691            0 :                         break;
    5692            0 :                 case DTC_Link_2:
    5693            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link2);
    5694            0 :                         break;
    5695            0 :                 case DTC_Link_3:
    5696            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link3);
    5697            0 :                         break;
    5698            0 :                 case DTC_Link_4:
    5699            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link4);
    5700            0 :                         break;
    5701            0 :                 case DTC_Link_5:
    5702            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_Link5);
    5703            0 :                         break;
    5704            0 :                 case DTC_Link_CFO:
    5705            0 :                         WriteRegister_(0, DTC_Register_RXCDRUnlockCount_CFOLink);
    5706            0 :                         break;
    5707            0 :                 default: {
    5708            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    5709            0 :                         __SS_THROW__;
    5710            0 :                 }
    5711              :         }
    5712            0 : }
    5713              : 
    5714            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink0()
    5715              : {
    5716            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link0);
    5717            0 :         form.description = "RX CDR Unlock Count Link 0";
    5718            0 :         std::stringstream o;
    5719            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_0, form.value);
    5720            0 :         form.vals.push_back(o.str());
    5721            0 :         return form;
    5722            0 : }
    5723              : 
    5724            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink1()
    5725              : {
    5726            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link1);
    5727            0 :         form.description = "RX CDR Unlock Count Link 1";
    5728            0 :         std::stringstream o;
    5729            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_1, form.value);
    5730            0 :         form.vals.push_back(o.str());
    5731            0 :         return form;
    5732            0 : }
    5733              : 
    5734            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink2()
    5735              : {
    5736            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link2);
    5737            0 :         form.description = "RX CDR Unlock Count Link 2";
    5738            0 :         std::stringstream o;
    5739            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_2, form.value);
    5740            0 :         form.vals.push_back(o.str());
    5741            0 :         return form;
    5742            0 : }
    5743              : 
    5744            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink3()
    5745              : {
    5746            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link3);
    5747            0 :         form.description = "RX CDR Unlock Count Link 3";
    5748            0 :         std::stringstream o;
    5749            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_3, form.value);
    5750            0 :         form.vals.push_back(o.str());
    5751            0 :         return form;
    5752            0 : }
    5753              : 
    5754            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink4()
    5755              : {
    5756            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link4);
    5757            0 :         form.description = "RX CDR Unlock Count Link 4";
    5758            0 :         std::stringstream o;
    5759            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_4, form.value);
    5760            0 :         form.vals.push_back(o.str());
    5761            0 :         return form;
    5762            0 : }
    5763              : 
    5764            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountLink5()
    5765              : {
    5766            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_Link5);
    5767            0 :         form.description = "RX CDR Unlock Count Link 5";
    5768            0 :         std::stringstream o;
    5769            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_5, form.value);
    5770            0 :         form.vals.push_back(o.str());
    5771            0 :         return form;
    5772            0 : }
    5773              : 
    5774            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCDRUnlockCountCFOLink()
    5775              : {
    5776            0 :         auto form = CreateFormatter(DTC_Register_RXCDRUnlockCount_CFOLink);
    5777            0 :         form.description = "RX CDR Unlock Count CFO Link";
    5778            0 :         std::stringstream o;
    5779            0 :         o << std::dec << ReadRXCDRUnlockCount(DTC_Link_CFO, form.value);
    5780            0 :         form.vals.push_back(o.str());
    5781            0 :         return form;
    5782            0 : }
    5783              : 
    5784            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorUnlockCount(std::optional<uint32_t> val)
    5785              : {
    5786            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuatorLossOfLockCount);
    5787              : }
    5788              : 
    5789            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorUnlockCount()
    5790              : {
    5791            0 :         WriteRegister_(1, DTC_Register_JitterAttenuatorLossOfLockCount);
    5792            0 : }
    5793              : 
    5794            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorUnlockCount()
    5795              : {
    5796            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuatorLossOfLockCount);
    5797            0 :         form.description = "RX Jitter Attenuator Unlock Count";
    5798            0 :         std::stringstream o;
    5799            0 :         o << std::dec << ReadJitterAttenuatorUnlockCount(form.value);
    5800            0 :         form.vals.push_back(o.str());
    5801            0 :         return form;
    5802            0 : }
    5803              : 
    5804            0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLinkEventStartCharacterErrorCount(std::optional<uint32_t> val)
    5805              : {
    5806            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLinkEventStartErrorCount);
    5807              : }
    5808              : 
    5809            0 : void DTCLib::DTC_Registers::ClearRXCFOLinkEventStartCharacterErrorCount()
    5810              : {
    5811            0 :         WriteRegister_(0, DTC_Register_CFOLinkEventStartErrorCount);
    5812            0 : }
    5813              : 
    5814            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLinkEventStartCharacterErrorCount()
    5815              : {
    5816            0 :         auto form = CreateFormatter(DTC_Register_CFOLinkEventStartErrorCount);
    5817            0 :         form.description = "CFO Link Event Start Error Count";
    5818            0 :         std::stringstream o;
    5819            0 :         o << std::dec << ReadRXCFOLinkEventStartCharacterErrorCount(form.value);
    5820            0 :         form.vals.push_back(o.str());
    5821            0 :         return form;
    5822            0 : }
    5823              : 
    5824            0 : uint32_t DTCLib::DTC_Registers::ReadRXCFOLink40MHzCharacterErrorCount(std::optional<uint32_t> val)
    5825              : {
    5826            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOLink40MHzErrorCount);
    5827              : }
    5828              : 
    5829            0 : void DTCLib::DTC_Registers::ClearRXCFOLink40MHzCharacterErrorCount()
    5830              : {
    5831            0 :         WriteRegister_(0, DTC_Register_CFOLink40MHzErrorCount);
    5832            0 : }
    5833              : 
    5834            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXCFOLink40MHzCharacterErrorCount()
    5835              : {
    5836            0 :         auto form = CreateFormatter(DTC_Register_CFOLink40MHzErrorCount);
    5837            0 :         form.description = "CFO Link 40 MHz Error Count";
    5838            0 :         std::stringstream o;
    5839            0 :         o << std::dec << ReadRXCFOLink40MHzCharacterErrorCount(form.value);
    5840            0 :         form.vals.push_back(o.str());
    5841            0 :         return form;
    5842            0 : }
    5843              : 
    5844            0 : uint32_t DTCLib::DTC_Registers::ReadInputBufferFragmentDumpCount(std::optional<uint32_t> val)
    5845              : {
    5846            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_InputBufferDropCount);
    5847              : }
    5848              : 
    5849            0 : void DTCLib::DTC_Registers::ClearInputBufferFragmentDumpCount()
    5850              : {
    5851            0 :         WriteRegister_(0, DTC_Register_InputBufferDropCount);
    5852            0 : }
    5853              : 
    5854            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatInputBufferFragmentDumpCount()
    5855              : {
    5856            0 :         auto form = CreateFormatter(DTC_Register_InputBufferDropCount);
    5857            0 :         form.description = "Input Buffer Fragment Drop Count";
    5858            0 :         std::stringstream o;
    5859            0 :         o << std::dec << ReadInputBufferFragmentDumpCount(form.value);
    5860            0 :         form.vals.push_back(o.str());
    5861            0 :         return form;
    5862            0 : }
    5863              : 
    5864            0 : uint32_t DTCLib::DTC_Registers::ReadOutputBufferFragmentDumpCount(std::optional<uint32_t> val)
    5865              : {
    5866            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_OutputBufferDropCount);
    5867              : }
    5868              : 
    5869            0 : void DTCLib::DTC_Registers::ClearOutputBufferFragmentDumpCount()
    5870              : {
    5871            0 :         WriteRegister_(0, DTC_Register_OutputBufferDropCount);
    5872            0 : }
    5873              : 
    5874            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatOutputBufferFragmentDumpCount()
    5875              : {
    5876            0 :         auto form = CreateFormatter(DTC_Register_OutputBufferDropCount);
    5877            0 :         form.description = "Output Buffer Fragment Drop Count";
    5878            0 :         std::stringstream o;
    5879            0 :         o << std::dec << ReadOutputBufferFragmentDumpCount(form.value);
    5880            0 :         form.vals.push_back(o.str());
    5881            0 :         return form;
    5882            0 : }
    5883              : 
    5884            0 : uint32_t DTCLib::DTC_Registers::ReadRTFHistIdelay(std::optional<uint32_t> val)
    5885              : {
    5886            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_RTFHistIdelay);
    5887              : }
    5888              : 
    5889            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRTFHistIdelay()
    5890              : {
    5891            0 :         auto form = CreateFormatter(DTC_Register_RTFHistIdelay);
    5892            0 :         form.description = "RTF Histogram & IDELAY Status";
    5893            0 :         form.vals.push_back("([ x = 1 (hi) ])");
    5894              : 
    5895            0 :         uint32_t idelay_tap = (form.value >> 27) & 0x1F;
    5896            0 :         form.vals.push_back(std::string("IDELAY Tap Count Value:      [") +
    5897            0 :                                                 std::to_string(idelay_tap) + "]");
    5898              : 
    5899            0 :         form.vals.push_back(std::string("IDELAY Ready:                [") +
    5900            0 :                                                 (((form.value >> 26) & 1) ? "x" : " ") + "]");
    5901              : 
    5902            0 :         form.vals.push_back("");
    5903              : 
    5904            0 :         form.vals.push_back("RTF Histogram Bins (3-bit counts, 0-7):");
    5905            0 :         for (int bin = 0; bin < 5; ++bin)
    5906              :         {
    5907            0 :                 int shift = 11 + bin * 3;
    5908            0 :                 uint32_t count = (form.value >> shift) & 0x7;
    5909            0 :                 form.vals.push_back(std::string("  Bin ") + std::to_string(bin) +
    5910            0 :                                                         ": [" + std::to_string(count) + "]");
    5911              :         }
    5912              : 
    5913            0 :         form.vals.push_back("");
    5914              : 
    5915            0 :         form.vals.push_back(std::string("Histogram Saturated:         [") +
    5916            0 :                                                 (((form.value >> 10) & 1) ? "x" : " ") + "]");
    5917              : 
    5918            0 :         uint32_t sat_bin = (form.value >> 7) & 0x7;
    5919            0 :         form.vals.push_back(std::string("Saturated Bin:               [") +
    5920            0 :                                                 std::to_string(sat_bin) + "]");
    5921              : 
    5922            0 :         std::stringstream rs;
    5923            0 :         rs << "0x" << std::hex << (form.value & 0x7F);
    5924            0 :         form.vals.push_back(std::string("Reserved [6:0]:              [") + rs.str() + "]");
    5925              : 
    5926            0 :         return form;
    5927            0 : }
    5928              : 
    5929            0 : void DTCLib::DTC_Registers::SetSoftwareDataRequest(const DTC_EventWindowTag& ts)
    5930              : {
    5931            0 :         auto timestamp = ts.GetEventWindowTag();
    5932            0 :         auto timestampLow = static_cast<uint32_t>(timestamp.to_ulong());
    5933            0 :         timestamp >>= 32;
    5934            0 :         auto timestampHigh = static_cast<uint16_t>(timestamp.to_ulong());
    5935              : 
    5936            0 :         WriteRegister_(timestampHigh, DTC_Register_DataRequest_High);
    5937            0 :         WriteRegister_(timestampLow, DTC_Register_DataRequest_Low);  // this triggers the DR
    5938            0 : }
    5939              : 
    5940            0 : DTCLib::DTC_EventWindowTag DTCLib::DTC_Registers::ReadSoftwareDataRequest(std::optional<uint32_t> val)
    5941              : {
    5942            0 :         auto timestampLow = val.has_value() ? *val : ReadRegister_(DTC_Register_DataRequest_Low);
    5943            0 :         DTC_EventWindowTag output;
    5944            0 :         output.SetEventWindowTag(timestampLow, static_cast<uint16_t>(ReadRegister_(DTC_Register_DataRequest_High)));
    5945            0 :         return output;
    5946            0 : }
    5947              : 
    5948            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestLow()
    5949              : {
    5950            0 :         auto form = CreateFormatter(DTC_Register_DataRequest_Low);
    5951            0 :         form.description = "Software Data Request Low";
    5952            0 :         std::stringstream o;
    5953            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_Low);
    5954            0 :         form.vals.push_back(o.str());
    5955            0 :         return form;
    5956            0 : }
    5957              : 
    5958            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSoftwareDataRequestHigh()
    5959              : {
    5960            0 :         auto form = CreateFormatter(DTC_Register_DataRequest_High);
    5961            0 :         form.description = "Software Data Request High";
    5962            0 :         std::stringstream o;
    5963            0 :         o << "0x" << std::hex << ReadRegister_(DTC_Register_DataRequest_High);
    5964            0 :         form.vals.push_back(o.str());
    5965            0 :         return form;
    5966            0 : }
    5967              : 
    5968              : // FPGA PROM Program Status Register
    5969              : /// <summary>
    5970              : /// Read the full bit on the FPGA PROM FIFO
    5971              : /// </summary>
    5972              : /// <returns>the full bit on the FPGA PROM FIFO</returns>
    5973            0 : bool DTCLib::DTC_Registers::ReadFPGAPROMProgramFIFOFull(std::optional<uint32_t> val)
    5974              : {
    5975            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
    5976            0 :         return dataSet[1];
    5977              : }
    5978              : 
    5979              : /// <summary>
    5980              : /// Read whether the FPGA PROM is ready for data
    5981              : /// </summary>
    5982              : /// <returns>whether the FPGA PROM is ready for data</returns>
    5983            0 : bool DTCLib::DTC_Registers::ReadFPGAPROMReady(std::optional<uint32_t> val)
    5984              : {
    5985            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGAPROMProgramStatus);
    5986            0 :         return dataSet[0];
    5987              : }
    5988              : 
    5989              : /// <summary>
    5990              : /// Formats the register's current value for register dumps
    5991              : /// </summary>
    5992              : /// <returns>RegisterFormatter object containing register information</returns>
    5993            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGAPROMProgramStatus()
    5994              : {
    5995            0 :         auto form = CreateFormatter(DTC_Register_FPGAPROMProgramStatus);
    5996            0 :         form.description = "FPGA PROM Program Status";
    5997            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    5998            0 :         form.vals.push_back(std::string("FPGA PROM Program FIFO Full: [") + (ReadFPGAPROMProgramFIFOFull(form.value) ? "x" : " ") +
    5999              :                                                 "]");
    6000            0 :         form.vals.push_back(std::string("FPGA PROM Ready:             [") + (ReadFPGAPROMReady(form.value) ? "x" : " ") + "]");
    6001            0 :         return form;
    6002            0 : }
    6003              : 
    6004              : // FPGA Core Access Register
    6005              : /// <summary>
    6006              : /// Performs the chants necessary to reload the DTC firmware
    6007              : /// </summary>
    6008            0 : void DTCLib::DTC_Registers::ReloadFPGAFirmware()
    6009              : {
    6010            0 :         WriteRegister_(0xFFFFFFFF, DTC_Register_FPGACoreAccess);
    6011            0 :         while (ReadFPGACoreAccessFIFOFull())
    6012              :         {
    6013            0 :                 usleep(10);
    6014              :         }
    6015            0 :         WriteRegister_(0xAA995566, DTC_Register_FPGACoreAccess);
    6016            0 :         while (ReadFPGACoreAccessFIFOFull())
    6017              :         {
    6018            0 :                 usleep(10);
    6019              :         }
    6020            0 :         WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
    6021            0 :         while (ReadFPGACoreAccessFIFOFull())
    6022              :         {
    6023            0 :                 usleep(10);
    6024              :         }
    6025            0 :         WriteRegister_(0x30020001, DTC_Register_FPGACoreAccess);
    6026            0 :         while (ReadFPGACoreAccessFIFOFull())
    6027              :         {
    6028            0 :                 usleep(10);
    6029              :         }
    6030            0 :         WriteRegister_(0x00000000, DTC_Register_FPGACoreAccess);
    6031            0 :         while (ReadFPGACoreAccessFIFOFull())
    6032              :         {
    6033            0 :                 usleep(10);
    6034              :         }
    6035            0 :         WriteRegister_(0x30008001, DTC_Register_FPGACoreAccess);
    6036            0 :         while (ReadFPGACoreAccessFIFOFull())
    6037              :         {
    6038            0 :                 usleep(10);
    6039              :         }
    6040            0 :         WriteRegister_(0x0000000F, DTC_Register_FPGACoreAccess);
    6041            0 :         while (ReadFPGACoreAccessFIFOFull())
    6042              :         {
    6043            0 :                 usleep(10);
    6044              :         }
    6045            0 :         WriteRegister_(0x20000000, DTC_Register_FPGACoreAccess);
    6046            0 : }
    6047              : 
    6048              : /// <summary>
    6049              : /// Read the FPGA Core Access FIFO Full bit
    6050              : /// </summary>
    6051              : /// <returns>Whether the FPGA Core Access FIFO is full</returns>
    6052            0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOFull(std::optional<uint32_t> val)
    6053              : {
    6054            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
    6055            0 :         return dataSet[1];
    6056              : }
    6057              : 
    6058              : /// <summary>
    6059              : /// Read the FPGA Core Access FIFO Empty bit
    6060              : /// </summary>
    6061              : /// <returns>Whether the FPGA Core Access FIFO is empty</returns>
    6062            0 : bool DTCLib::DTC_Registers::ReadFPGACoreAccessFIFOEmpty(std::optional<uint32_t> val)
    6063              : {
    6064            0 :         std::bitset<32> dataSet = val.has_value() ? *val : ReadRegister_(DTC_Register_FPGACoreAccess);
    6065            0 :         return dataSet[0];
    6066              : }
    6067              : 
    6068              : /// <summary>
    6069              : /// Formats the register's current value for register dumps
    6070              : /// </summary>
    6071              : /// <returns>RegisterFormatter object containing register information</returns>
    6072            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatFPGACoreAccess()
    6073              : {
    6074            0 :         auto form = CreateFormatter(DTC_Register_FPGACoreAccess);
    6075            0 :         form.description = "FPGA Core Access";
    6076            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6077            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Full:  [") + (ReadFPGACoreAccessFIFOFull(form.value) ? "x" : " ") + "]");
    6078            0 :         form.vals.push_back(std::string("FPGA Core Access FIFO Empty: [") + (ReadFPGACoreAccessFIFOEmpty(form.value) ? "x" : " ") +
    6079              :                                                 "]");
    6080              : 
    6081            0 :         return form;
    6082            0 : }
    6083              : 
    6084            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
    6085              : {
    6086            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6087            0 :         return data[9];
    6088              : }
    6089              : 
    6090            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
    6091              : {
    6092            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6093            0 :         return data[8];
    6094              : }
    6095              : 
    6096            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
    6097              : {
    6098            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6099            0 :         return data[7];
    6100              : }
    6101              : 
    6102            0 : bool DTCLib::DTC_Registers::ReadRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
    6103              : {
    6104            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6105            0 :         return data[6];
    6106              : }
    6107              : 
    6108            0 : bool DTCLib::DTC_Registers::ReadLatchedSpareSMAInputOKError(std::optional<uint32_t> val)
    6109              : {
    6110            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6111            0 :         return data[5];
    6112              : }
    6113              : 
    6114            0 : void DTCLib::DTC_Registers::ClearLatchedSpareSMAInputOKError()
    6115              : {
    6116            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6117            0 :         data[5] = 1;
    6118            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6119            0 : }
    6120              : 
    6121            0 : bool DTCLib::DTC_Registers::ReadLatchedEventMarkerSMAInputOKError(std::optional<uint32_t> val)
    6122              : {
    6123            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6124            0 :         return data[4];
    6125              : }
    6126              : 
    6127            0 : void DTCLib::DTC_Registers::ClearLatchedEventMarkerSMASMAInputOKError()
    6128              : {
    6129            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6130            0 :         data[4] = 1;
    6131            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6132            0 : }
    6133              : 
    6134            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink3(std::optional<uint32_t> val)
    6135              : {
    6136            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6137            0 :         return data[3];
    6138              : }
    6139              : 
    6140            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink3()
    6141              : {
    6142            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6143            0 :         data[3] = 1;
    6144            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6145            0 : }
    6146              : 
    6147            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink2(std::optional<uint32_t> val)
    6148              : {
    6149            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6150            0 :         return data[2];
    6151              : }
    6152              : 
    6153            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink2()
    6154              : {
    6155            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6156            0 :         data[2] = 1;
    6157            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6158            0 : }
    6159              : 
    6160            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink1(std::optional<uint32_t> val)
    6161              : {
    6162            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6163            0 :         return data[1];
    6164              : }
    6165              : 
    6166            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink1()
    6167              : {
    6168            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6169            0 :         data[1] = 1;
    6170            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6171            0 : }
    6172              : 
    6173            0 : bool DTCLib::DTC_Registers::ReadLatchedRXOKErrorSlowOpticalLink0(std::optional<uint32_t> val)
    6174              : {
    6175            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6176            0 :         return data[0];
    6177              : }
    6178              : 
    6179            0 : void DTCLib::DTC_Registers::ClearLatchedRXOKErrorSlowOpticalLink0()
    6180              : {
    6181            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_SlowOpticalLinksDiag);
    6182            0 :         data[0] = 1;
    6183            0 :         WriteRegister_(data.to_ulong(), DTC_Register_SlowOpticalLinksDiag);
    6184            0 : }
    6185              : 
    6186            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSlowOpticalLinkControlStatus()
    6187              : {
    6188            0 :         auto form = CreateFormatter(DTC_Register_SFPControlStatus);
    6189            0 :         form.description = "Slow Optical Link Control Status";
    6190            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6191            0 :         form.vals.push_back(std::string("RX OK SOL Link 3:           [") + (ReadRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
    6192            0 :         form.vals.push_back(std::string("RX OK SOL Link 2:           [") + (ReadRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
    6193            0 :         form.vals.push_back(std::string("RX OK SOL Link 1:           [") + (ReadRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
    6194            0 :         form.vals.push_back(std::string("RX OK SOL Link 0:           [") + (ReadRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
    6195            0 :         form.vals.push_back(std::string("Latched Spare SMA Input:    [") + (ReadLatchedSpareSMAInputOKError(form.value) ? "x" : " ") + "]");
    6196            0 :         form.vals.push_back(std::string("Latched Event Marker Input: [") + (ReadLatchedEventMarkerSMAInputOKError(form.value) ? "x" : " ") + "]");
    6197            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 3:   [") + (ReadLatchedRXOKErrorSlowOpticalLink3(form.value) ? "x" : " ") + "]");
    6198            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 2:   [") + (ReadLatchedRXOKErrorSlowOpticalLink2(form.value) ? "x" : " ") + "]");
    6199            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 1:   [") + (ReadLatchedRXOKErrorSlowOpticalLink1(form.value) ? "x" : " ") + "]");
    6200            0 :         form.vals.push_back(std::string("Latched RX OK SOL Link 0:   [") + (ReadLatchedRXOKErrorSlowOpticalLink0(form.value) ? "x" : " ") + "]");
    6201            0 :         return form;
    6202            0 : }
    6203              : 
    6204            0 : bool DTCLib::DTC_Registers::ReadSERDESInduceErrorEnable(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6205              : {
    6206            0 :         std::bitset<32> data = val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
    6207            0 :         return data[link];
    6208              : }
    6209              : 
    6210            0 : void DTCLib::DTC_Registers::EnableSERDESInduceError(DTC_Link_ID const& link)
    6211              : {
    6212            0 :         SetBit_(DTC_Register_DiagSERDESErrorEnable, link, true);
    6213            0 : }
    6214              : 
    6215            0 : void DTCLib::DTC_Registers::DisableSERDESInduceError(DTC_Link_ID const& link)
    6216              : {
    6217            0 :         std::bitset<32> data = ReadRegister_(DTC_Register_DiagSERDESErrorEnable);
    6218            0 :         data[link] = 0;
    6219            0 :         WriteRegister_(data.to_ulong(), DTC_Register_DiagSERDESErrorEnable);
    6220            0 : }
    6221              : 
    6222            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorEnable()
    6223              : {
    6224            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    6225            0 :         form.description = "SERDES Induce Error Enable";
    6226            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    6227            0 :         for (auto r : DTC_ROC_Links)
    6228            0 :                 form.vals.push_back(std::string("Link ") + std::to_string(r) + ": [" +
    6229            0 :                                                         (ReadSERDESInduceErrorEnable(r, form.value) ? "x" : " ") + "]");
    6230              : 
    6231            0 :         return form;
    6232            0 : }
    6233              : 
    6234            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6235              : {
    6236            0 :         switch (link)
    6237              :         {
    6238            0 :                 case DTC_Link_0:
    6239            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket0);
    6240            0 :                 case DTC_Link_1:
    6241            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket1);
    6242            0 :                 case DTC_Link_2:
    6243            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket2);
    6244            0 :                 case DTC_Link_3:
    6245            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket3);
    6246            0 :                 case DTC_Link_4:
    6247            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket4);
    6248            0 :                 case DTC_Link_5:
    6249            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DiagSERDESPacket5);
    6250            0 :                 default: {
    6251            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6252            0 :                         __SS_THROW__;
    6253            0 :                 }
    6254              :         }
    6255              : }
    6256              : 
    6257            0 : void DTCLib::DTC_Registers::SetSERDESInduceErrorSequenceNumber(DTC_Link_ID const& link, uint32_t sequence)
    6258              : {
    6259            0 :         switch (link)
    6260              :         {
    6261            0 :                 case DTC_Link_0:
    6262            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket0);
    6263            0 :                         break;
    6264            0 :                 case DTC_Link_1:
    6265            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket1);
    6266            0 :                         break;
    6267            0 :                 case DTC_Link_2:
    6268            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket2);
    6269            0 :                         break;
    6270            0 :                 case DTC_Link_3:
    6271            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket3);
    6272            0 :                         break;
    6273            0 :                 case DTC_Link_4:
    6274            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket4);
    6275            0 :                         break;
    6276            0 :                 case DTC_Link_5:
    6277            0 :                         WriteRegister_(sequence, DTC_Register_DiagSERDESPacket5);
    6278            0 :                         break;
    6279            0 :                 default: {
    6280            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6281            0 :                         __SS_THROW__;
    6282            0 :                 }
    6283              :         }
    6284            0 : }
    6285              : 
    6286            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink0()
    6287              : {
    6288            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket0);
    6289            0 :         form.description = "Link 0 Induced Error Sequence Number";
    6290            0 :         std::stringstream o;
    6291            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_0, form.value);
    6292            0 :         form.vals.push_back(o.str());
    6293            0 :         return form;
    6294            0 : }
    6295              : 
    6296            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink1()
    6297              : {
    6298            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket1);
    6299            0 :         form.description = "Link 1 Induced Error Sequence Number";
    6300            0 :         std::stringstream o;
    6301            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_1, form.value);
    6302            0 :         form.vals.push_back(o.str());
    6303            0 :         return form;
    6304            0 : }
    6305              : 
    6306            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink2()
    6307              : {
    6308            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket2);
    6309            0 :         form.description = "Link 2 Induced Error Sequence Number";
    6310            0 :         std::stringstream o;
    6311            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_2, form.value);
    6312            0 :         form.vals.push_back(o.str());
    6313            0 :         return form;
    6314            0 : }
    6315              : 
    6316            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink3()
    6317              : {
    6318            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket3);
    6319            0 :         form.description = "Link 3 Induced Error Sequence Number";
    6320            0 :         std::stringstream o;
    6321            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_3, form.value);
    6322            0 :         form.vals.push_back(o.str());
    6323            0 :         return form;
    6324            0 : }
    6325              : 
    6326            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink4()
    6327              : {
    6328            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket4);
    6329            0 :         form.description = "Link 4 Induced Error Sequence Number";
    6330            0 :         std::stringstream o;
    6331            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_4, form.value);
    6332            0 :         form.vals.push_back(o.str());
    6333            0 :         return form;
    6334            0 : }
    6335              : 
    6336            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESInduceErrorSequenceNumberLink5()
    6337              : {
    6338            0 :         auto form = CreateFormatter(DTC_Register_DiagSERDESPacket5);
    6339            0 :         form.description = "Link 5 Induced Error Sequence Number";
    6340            0 :         std::stringstream o;
    6341            0 :         o << std::dec << ReadSERDESInduceErrorSequenceNumber(DTC_Link_5, form.value);
    6342            0 :         form.vals.push_back(o.str());
    6343            0 :         return form;
    6344            0 : }
    6345              : 
    6346              : // DTCLib::DTC_DDRFlags DTCLib::DTC_Registers::ReadDDRFlags(uint8_t buffer_id)
    6347              : // {
    6348              : //      return DTC_DDRFlags(ReadDDRLinkBufferFullFlags()[buffer_id],
    6349              : //                                              ReadDDRLinkBufferEmptyFlags()[buffer_id],
    6350              : //                                              ReadDDRLinkBufferHalfFullFlags()[buffer_id],
    6351              : //                                              ReadDDREventBuilderBufferFullFlags()[buffer_id],
    6352              : //                                              ReadDDREventBuilderBufferEmptyFlags()[buffer_id],
    6353              : //                                              ReadDDREventBuilderBufferHalfFullFlags()[buffer_id]);
    6354              : // }
    6355              : 
    6356              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferFullFlags()
    6357              : // {
    6358              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags0);
    6359              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags1);
    6360              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags2);
    6361              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferFullFlags3);
    6362              : //      std::bitset<128> out;
    6363              : //      for (size_t ii = 0; ii < 32; ++ii)
    6364              : //      {
    6365              : //              out[ii] = (word0 >> ii) & 0x1;
    6366              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6367              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6368              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6369              : //      }
    6370              : //      return out;
    6371              : // }
    6372              : 
    6373              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferEmptyFlags()
    6374              : // {
    6375              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6376              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6377              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6378              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6379              : //      std::bitset<128> out;
    6380              : //      for (size_t ii = 0; ii < 32; ++ii)
    6381              : //      {
    6382              : //              out[ii] = (word0 >> ii) & 0x1;
    6383              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6384              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6385              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6386              : //      }
    6387              : //      return out;
    6388              : // }
    6389              : 
    6390              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDRLinkBufferHalfFullFlags()
    6391              : // {
    6392              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6393              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6394              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6395              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6396              : //      std::bitset<128> out;
    6397              : //      for (size_t ii = 0; ii < 32; ++ii)
    6398              : //      {
    6399              : //              out[ii] = (word0 >> ii) & 0x1;
    6400              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6401              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6402              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6403              : //      }
    6404              : //      return out;
    6405              : // }
    6406              : 
    6407              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferFullFlags()
    6408              : // {
    6409              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags0);
    6410              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags1);
    6411              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags2);
    6412              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferFullFlags3);
    6413              : //      std::bitset<128> out;
    6414              : //      for (size_t ii = 0; ii < 32; ++ii)
    6415              : //      {
    6416              : //              out[ii] = (word0 >> ii) & 0x1;
    6417              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6418              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6419              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6420              : //      }
    6421              : //      return out;
    6422              : // }
    6423              : 
    6424              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferEmptyFlags()
    6425              : // {
    6426              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags0);
    6427              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags1);
    6428              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags2);
    6429              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferEmptyFlags3);
    6430              : //      std::bitset<128> out;
    6431              : //      for (size_t ii = 0; ii < 32; ++ii)
    6432              : //      {
    6433              : //              out[ii] = (word0 >> ii) & 0x1;
    6434              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6435              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6436              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6437              : //      }
    6438              : //      return out;
    6439              : // }
    6440              : 
    6441              : // std::bitset<128> DTCLib::DTC_Registers::ReadDDREventBuilderBufferHalfFullFlags()
    6442              : // {
    6443              : //      uint32_t word0 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags0);
    6444              : //      uint32_t word1 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags1);
    6445              : //      uint32_t word2 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags2);
    6446              : //      uint32_t word3 = ReadRegister_(DTC_Register_DDR3EVBBufferHalfFullFlags3);
    6447              : //      std::bitset<128> out;
    6448              : //      for (size_t ii = 0; ii < 32; ++ii)
    6449              : //      {
    6450              : //              out[ii] = (word0 >> ii) & 0x1;
    6451              : //              out[ii + 32] = (word1 >> ii) & 0x1;
    6452              : //              out[ii + 64] = (word2 >> ii) & 0x1;
    6453              : //              out[ii + 96] = (word3 >> ii) & 0x1;
    6454              : //      }
    6455              : //      return out;
    6456              : // }
    6457              : 
    6458              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags0()
    6459              : // {
    6460              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6461              : //      form.description = "DDR Link Buffer Empty Flags 0-31";
    6462              : //      return form;
    6463              : // }
    6464              : 
    6465              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags1()
    6466              : // {
    6467              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6468              : //      form.description = "DDR Link Buffer Empty Flags 63-32";
    6469              : //      return form;
    6470              : // }
    6471              : 
    6472              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags2()
    6473              : // {
    6474              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6475              : //      form.description = "DDR Link Buffer Empty Flags 95-64";
    6476              : //      return form;
    6477              : // }
    6478              : 
    6479              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferEmptyFlags3()
    6480              : // {
    6481              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6482              : //      form.description = "DDR Link Buffer Empty Flags 127-96";
    6483              : //      return form;
    6484              : // }
    6485              : 
    6486              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags0()
    6487              : // {
    6488              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6489              : //      form.description = "DDR Link Buffer Half-Full Flags 0-31";
    6490              : //      return form;
    6491              : // }
    6492              : 
    6493              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags1()
    6494              : // {
    6495              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6496              : //      form.description = "DDR Link Buffer Half-Full Flags 63-32";
    6497              : //      return form;
    6498              : // }
    6499              : 
    6500              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags2()
    6501              : // {
    6502              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6503              : //      form.description = "DDR Link Buffer Half-Full Flags 95-64";
    6504              : //      return form;
    6505              : // }
    6506              : 
    6507              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferHalfFullFlags3()
    6508              : // {
    6509              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6510              : //      form.description = "DDR Link Buffer Half-Full Flags 127-96";
    6511              : //      return form;
    6512              : // }
    6513              : 
    6514              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags0()
    6515              : // {
    6516              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags0);
    6517              : //      form.description = "DDR Link Buffer Full Flags 0-31";
    6518              : //      return form;
    6519              : // }
    6520              : 
    6521              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags1()
    6522              : // {
    6523              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags1);
    6524              : //      form.description = "DDR Link Buffer Full Flags 63-32";
    6525              : //      return form;
    6526              : // }
    6527              : 
    6528              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags2()
    6529              : // {
    6530              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags2);
    6531              : //      form.description = "DDR Link Buffer Full Flags 95-64";
    6532              : //      return form;
    6533              : // }
    6534              : 
    6535              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDRLinkBufferFullFlags3()
    6536              : // {
    6537              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferEmptyFlags3);
    6538              : //      form.description = "DDR Link Buffer Full Flags 127-96";
    6539              : //      return form;
    6540              : // }
    6541              : 
    6542              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags0()
    6543              : // {
    6544              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags0);
    6545              : //      form.description = "DDR EVB Buffer Empty Flags 0-31";
    6546              : //      return form;
    6547              : // }
    6548              : 
    6549              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags1()
    6550              : // {
    6551              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags1);
    6552              : //      form.description = "DDR EVB Buffer Empty Flags 63-32";
    6553              : //      return form;
    6554              : // }
    6555              : 
    6556              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags2()
    6557              : // {
    6558              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags2);
    6559              : //      form.description = "DDR EVB Buffer Empty Flags 95-64";
    6560              : //      return form;
    6561              : // }
    6562              : 
    6563              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferEmptyFlags3()
    6564              : // {
    6565              : //      auto form = CreateFormatter(DTC_Register_DDR3EVBBufferEmptyFlags3);
    6566              : //      form.description = "DDR EVB Buffer Empty Flags 127-96";
    6567              : //      return form;
    6568              : // }
    6569              : 
    6570              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags0()
    6571              : // {
    6572              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags0);
    6573              : //      form.description = "DDR Link Buffer Half-Full Flags 0-31";
    6574              : //      return form;
    6575              : // }
    6576              : 
    6577              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags1()
    6578              : // {
    6579              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags1);
    6580              : //      form.description = "DDR Link Buffer Half-Full Flags 63-32";
    6581              : //      return form;
    6582              : // }
    6583              : 
    6584              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags2()
    6585              : // {
    6586              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags2);
    6587              : //      form.description = "DDR Link Buffer Half-Full Flags 95-64";
    6588              : //      return form;
    6589              : // }
    6590              : 
    6591              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferHalfFullFlags3()
    6592              : // {
    6593              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferHalfFullFlags3);
    6594              : //      form.description = "DDR Link Buffer Half-Full Flags 127-96";
    6595              : //      return form;
    6596              : // }
    6597              : 
    6598              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags0()
    6599              : // {
    6600              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags0);
    6601              : //      form.description = "DDR Link Buffer Full Flags 0-31";
    6602              : //      return form;
    6603              : // }
    6604              : 
    6605              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags1()
    6606              : // {
    6607              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags1);
    6608              : //      form.description = "DDR Link Buffer Full Flags 63-32";
    6609              : //      return form;
    6610              : // }
    6611              : 
    6612              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags2()
    6613              : // {
    6614              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags2);
    6615              : //      form.description = "DDR Link Buffer Full Flags 95-64";
    6616              : //      return form;
    6617              : // }
    6618              : 
    6619              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDDREventBuilderBufferFullFlags3()
    6620              : // {
    6621              : //      auto form = CreateFormatter(DTC_Register_DDR3LinkBufferFullFlags3);
    6622              : //      form.description = "DDR Link Buffer Full Flags 127-96";
    6623              : //      return form;
    6624              : // }
    6625              : 
    6626            0 : uint32_t DTCLib::DTC_Registers::ReadDataPendingDiagnosticTimer(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6627              : {
    6628            0 :         switch (link)
    6629              :         {
    6630            0 :                 case DTC_Link_0:
    6631            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link0);
    6632            0 :                 case DTC_Link_1:
    6633            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link1);
    6634            0 :                 case DTC_Link_2:
    6635            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link2);
    6636            0 :                 case DTC_Link_3:
    6637            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link3);
    6638            0 :                 case DTC_Link_4:
    6639            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link4);
    6640            0 :                 case DTC_Link_5:
    6641            0 :                         return val.has_value() ? *val : ReadRegister_(DTC_Register_DataPendingDiagTimer_Link5);
    6642            0 :                 default: {
    6643            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6644            0 :                         __SS_THROW__;
    6645            0 :                 }
    6646              :         }
    6647              : }
    6648              : 
    6649            0 : void DTCLib::DTC_Registers::ResetDataPendingDiagnosticTimerFIFO(DTC_Link_ID const& link)
    6650              : {
    6651            0 :         switch (link)
    6652              :         {
    6653            0 :                 case DTC_Link_0:
    6654            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link0);
    6655            0 :                         break;
    6656            0 :                 case DTC_Link_1:
    6657            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link1);
    6658            0 :                         break;
    6659            0 :                 case DTC_Link_2:
    6660            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link2);
    6661            0 :                         break;
    6662            0 :                 case DTC_Link_3:
    6663            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link3);
    6664            0 :                         break;
    6665            0 :                 case DTC_Link_4:
    6666            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link4);
    6667            0 :                         break;
    6668            0 :                 case DTC_Link_5:
    6669            0 :                         WriteRegister_(0, DTC_Register_DataPendingDiagTimer_Link5);
    6670            0 :                         break;
    6671            0 :                 default: {
    6672            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6673            0 :                         __SS_THROW__;
    6674            0 :                 }
    6675              :         }
    6676            0 : }
    6677              : 
    6678            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink0()
    6679              : {
    6680            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link0);
    6681            0 :         form.description = "Data Pending Diagnostic Timer Link 0";
    6682            0 :         std::stringstream o;
    6683            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_0, form.value);
    6684            0 :         form.vals.push_back(o.str());
    6685            0 :         return form;
    6686            0 : }
    6687              : 
    6688            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink1()
    6689              : {
    6690            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link1);
    6691            0 :         form.description = "Data Pending Diagnostic Timer Link 1";
    6692            0 :         std::stringstream o;
    6693            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_1, form.value);
    6694            0 :         form.vals.push_back(o.str());
    6695            0 :         return form;
    6696            0 : }
    6697              : 
    6698            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink2()
    6699              : {
    6700            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link2);
    6701            0 :         form.description = "Data Pending Diagnostic Timer Link 2";
    6702            0 :         std::stringstream o;
    6703            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_2, form.value);
    6704            0 :         form.vals.push_back(o.str());
    6705            0 :         return form;
    6706            0 : }
    6707              : 
    6708            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink3()
    6709              : {
    6710            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link3);
    6711            0 :         form.description = "Data Pending Diagnostic Timer Link 3";
    6712            0 :         std::stringstream o;
    6713            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_3, form.value);
    6714            0 :         form.vals.push_back(o.str());
    6715            0 :         return form;
    6716            0 : }
    6717              : 
    6718            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink4()
    6719              : {
    6720            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link4);
    6721            0 :         form.description = "Data Pending Diagnostic Timer Link 4";
    6722            0 :         std::stringstream o;
    6723            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_4, form.value);
    6724            0 :         form.vals.push_back(o.str());
    6725            0 :         return form;
    6726            0 : }
    6727              : 
    6728            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDataPendingDiagnosticTimerLink5()
    6729              : {
    6730            0 :         auto form = CreateFormatter(DTC_Register_DataPendingDiagTimer_Link5);
    6731            0 :         form.description = "Data Pending Diagnostic Timer Link 5";
    6732            0 :         std::stringstream o;
    6733            0 :         o << std::dec << ReadDataPendingDiagnosticTimer(DTC_Link_5, form.value);
    6734            0 :         form.vals.push_back(o.str());
    6735            0 :         return form;
    6736            0 : }
    6737              : 
    6738            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6739              : {
    6740              :         DTC_Register reg;
    6741            0 :         switch (link)
    6742              :         {
    6743            0 :                 case DTC_Link_0:
    6744            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
    6745            0 :                         break;
    6746            0 :                 case DTC_Link_1:
    6747            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
    6748            0 :                         break;
    6749            0 :                 case DTC_Link_2:
    6750            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
    6751            0 :                         break;
    6752            0 :                 case DTC_Link_3:
    6753            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
    6754            0 :                         break;
    6755            0 :                 case DTC_Link_4:
    6756            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
    6757            0 :                         break;
    6758            0 :                 case DTC_Link_5:
    6759            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
    6760            0 :                         break;
    6761            0 :                 case DTC_Link_CFO:
    6762            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
    6763            0 :                         break;
    6764            0 :                 default: {
    6765            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6766            0 :                         __SS_THROW__;
    6767            0 :                 }
    6768              :         }
    6769            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    6770              : }
    6771            0 : void DTCLib::DTC_Registers::ClearSERDESCharacterNotInTableErrorCount(DTC_Link_ID const& link)
    6772              : {
    6773              :         DTC_Register reg;
    6774            0 :         switch (link)
    6775              :         {
    6776            0 :                 case DTC_Link_0:
    6777            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0;
    6778            0 :                         break;
    6779            0 :                 case DTC_Link_1:
    6780            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1;
    6781            0 :                         break;
    6782            0 :                 case DTC_Link_2:
    6783            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2;
    6784            0 :                         break;
    6785            0 :                 case DTC_Link_3:
    6786            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3;
    6787            0 :                         break;
    6788            0 :                 case DTC_Link_4:
    6789            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4;
    6790            0 :                         break;
    6791            0 :                 case DTC_Link_5:
    6792            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5;
    6793            0 :                         break;
    6794            0 :                 case DTC_Link_CFO:
    6795            0 :                         reg = DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink;
    6796            0 :                         break;
    6797            0 :                 default: {
    6798            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6799            0 :                         __SS_THROW__;
    6800            0 :                 }
    6801              :         }
    6802            0 :         WriteRegister_(1, reg);
    6803            0 : }
    6804              : 
    6805            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink0()
    6806              : {
    6807            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link0);
    6808            0 :         form.description = "SERDES Character Not In Table Error Count Link 0";
    6809            0 :         std::stringstream o;
    6810            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_0);
    6811            0 :         form.vals.push_back(o.str());
    6812            0 :         return form;
    6813            0 : }
    6814            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink1()
    6815              : {
    6816            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link1);
    6817            0 :         form.description = "SERDES Character Not In Table Error Count Link 1";
    6818            0 :         std::stringstream o;
    6819            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_1);
    6820            0 :         form.vals.push_back(o.str());
    6821            0 :         return form;
    6822            0 : }
    6823            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink2()
    6824              : {
    6825            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link2);
    6826            0 :         form.description = "SERDES Character Not In Table Error Count Link 2";
    6827            0 :         std::stringstream o;
    6828            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_2);
    6829            0 :         form.vals.push_back(o.str());
    6830            0 :         return form;
    6831            0 : }
    6832            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink3()
    6833              : {
    6834            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link3);
    6835            0 :         form.description = "SERDES Character Not In Table Error Count Link 3";
    6836            0 :         std::stringstream o;
    6837            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_3);
    6838            0 :         form.vals.push_back(o.str());
    6839            0 :         return form;
    6840            0 : }
    6841            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink4()
    6842              : {
    6843            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link4);
    6844            0 :         form.description = "SERDES Character Not In Table Error Count Link 4";
    6845            0 :         std::stringstream o;
    6846            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_4);
    6847            0 :         form.vals.push_back(o.str());
    6848            0 :         return form;
    6849            0 : }
    6850            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountLink5()
    6851              : {
    6852            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_Link5);
    6853            0 :         form.description = "SERDES Character Not In Table Error Count Link 5";
    6854            0 :         std::stringstream o;
    6855            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_5);
    6856            0 :         form.vals.push_back(o.str());
    6857            0 :         return form;
    6858            0 : }
    6859            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESCharacterNotInTableErrorCountCFOLink()
    6860              : {
    6861            0 :         auto form = CreateFormatter(DTC_Register_SERDES_CharacterNotInTableErrorCount_CFOLink);
    6862            0 :         form.description = "SERDES Character Not In Table Error Count CFO Link";
    6863            0 :         std::stringstream o;
    6864            0 :         o << std::dec << ReadSERDESCharacterNotInTableErrorCount(DTC_Link_CFO);
    6865            0 :         form.vals.push_back(o.str());
    6866            0 :         return form;
    6867            0 : }
    6868              : 
    6869            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXDisparityErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    6870              : {
    6871              :         DTC_Register reg;
    6872            0 :         switch (link)
    6873              :         {
    6874            0 :                 case DTC_Link_0:
    6875            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
    6876            0 :                         break;
    6877            0 :                 case DTC_Link_1:
    6878            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
    6879            0 :                         break;
    6880            0 :                 case DTC_Link_2:
    6881            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
    6882            0 :                         break;
    6883            0 :                 case DTC_Link_3:
    6884            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
    6885            0 :                         break;
    6886            0 :                 case DTC_Link_4:
    6887            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
    6888            0 :                         break;
    6889            0 :                 case DTC_Link_5:
    6890            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
    6891            0 :                         break;
    6892            0 :                 case DTC_Link_CFO:
    6893            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
    6894            0 :                         break;
    6895            0 :                 default: {
    6896            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6897            0 :                         __SS_THROW__;
    6898            0 :                 }
    6899              :         }
    6900            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    6901              : }
    6902            0 : void DTCLib::DTC_Registers::ClearSERDESRXDisparityErrorCount(DTC_Link_ID const& link)
    6903              : {
    6904              :         DTC_Register reg;
    6905            0 :         switch (link)
    6906              :         {
    6907            0 :                 case DTC_Link_0:
    6908            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link0;
    6909            0 :                         break;
    6910            0 :                 case DTC_Link_1:
    6911            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link1;
    6912            0 :                         break;
    6913            0 :                 case DTC_Link_2:
    6914            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link2;
    6915            0 :                         break;
    6916            0 :                 case DTC_Link_3:
    6917            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link3;
    6918            0 :                         break;
    6919            0 :                 case DTC_Link_4:
    6920            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link4;
    6921            0 :                         break;
    6922            0 :                 case DTC_Link_5:
    6923            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_Link5;
    6924            0 :                         break;
    6925            0 :                 case DTC_Link_CFO:
    6926            0 :                         reg = DTC_Register_SERDES_RXDisparityErrorCount_CFOLink;
    6927            0 :                         break;
    6928            0 :                 default: {
    6929            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    6930            0 :                         __SS_THROW__;
    6931            0 :                 }
    6932              :         }
    6933            0 :         WriteRegister_(1, reg);
    6934            0 : }
    6935              : 
    6936            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink0()
    6937              : {
    6938            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link0);
    6939            0 :         form.description = "SERDES RX Disparity Error Count Link 0";
    6940            0 :         std::stringstream o;
    6941            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_0, form.value);
    6942            0 :         form.vals.push_back(o.str());
    6943            0 :         return form;
    6944            0 : }
    6945            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink1()
    6946              : {
    6947            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link1);
    6948            0 :         form.description = "SERDES RX Disparity Error Count Link 1";
    6949            0 :         std::stringstream o;
    6950            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_1, form.value);
    6951            0 :         form.vals.push_back(o.str());
    6952            0 :         return form;
    6953            0 : }
    6954            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink2()
    6955              : {
    6956            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link2);
    6957            0 :         form.description = "SERDES RX Disparity Error Count Link 2";
    6958            0 :         std::stringstream o;
    6959            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_2, form.value);
    6960            0 :         form.vals.push_back(o.str());
    6961            0 :         return form;
    6962            0 : }
    6963            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink3()
    6964              : {
    6965            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link3);
    6966            0 :         form.description = "SERDES RX Disparity Error Count Link 3";
    6967            0 :         std::stringstream o;
    6968            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_3, form.value);
    6969            0 :         form.vals.push_back(o.str());
    6970            0 :         return form;
    6971            0 : }
    6972            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink4()
    6973              : {
    6974            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link4);
    6975            0 :         form.description = "SERDES RX Disparity Error Count Link 4";
    6976            0 :         std::stringstream o;
    6977            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_4, form.value);
    6978            0 :         form.vals.push_back(o.str());
    6979            0 :         return form;
    6980            0 : }
    6981            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountLink5()
    6982              : {
    6983            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_Link5);
    6984            0 :         form.description = "SERDES RX Disparity Error Count Link 5";
    6985            0 :         std::stringstream o;
    6986            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_5, form.value);
    6987            0 :         form.vals.push_back(o.str());
    6988            0 :         return form;
    6989            0 : }
    6990            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXDisparityErrorCountCFOLink()
    6991              : {
    6992            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXDisparityErrorCount_CFOLink);
    6993            0 :         form.description = "SERDES RX Disparity Error Count CFO Link";
    6994            0 :         std::stringstream o;
    6995            0 :         o << std::dec << ReadSERDESRXDisparityErrorCount(DTC_Link_CFO, form.value);
    6996            0 :         form.vals.push_back(o.str());
    6997            0 :         return form;
    6998            0 : }
    6999              : 
    7000            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXPRBSErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7001              : {
    7002              :         DTC_Register reg;
    7003            0 :         switch (link)
    7004              :         {
    7005            0 :                 case DTC_Link_0:
    7006            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
    7007            0 :                         break;
    7008            0 :                 case DTC_Link_1:
    7009            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
    7010            0 :                         break;
    7011            0 :                 case DTC_Link_2:
    7012            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
    7013            0 :                         break;
    7014            0 :                 case DTC_Link_3:
    7015            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
    7016            0 :                         break;
    7017            0 :                 case DTC_Link_4:
    7018            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
    7019            0 :                         break;
    7020            0 :                 case DTC_Link_5:
    7021            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
    7022            0 :                         break;
    7023            0 :                 case DTC_Link_CFO:
    7024            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
    7025            0 :                         break;
    7026            0 :                 default: {
    7027            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7028            0 :                         __SS_THROW__;
    7029            0 :                 }
    7030              :         }
    7031            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    7032              : }
    7033            0 : void DTCLib::DTC_Registers::ClearSERDESRXPRBSErrorCount(DTC_Link_ID const& link)
    7034              : {
    7035              :         DTC_Register reg;
    7036            0 :         switch (link)
    7037              :         {
    7038            0 :                 case DTC_Link_0:
    7039            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link0;
    7040            0 :                         break;
    7041            0 :                 case DTC_Link_1:
    7042            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link1;
    7043            0 :                         break;
    7044            0 :                 case DTC_Link_2:
    7045            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link2;
    7046            0 :                         break;
    7047            0 :                 case DTC_Link_3:
    7048            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link3;
    7049            0 :                         break;
    7050            0 :                 case DTC_Link_4:
    7051            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link4;
    7052            0 :                         break;
    7053            0 :                 case DTC_Link_5:
    7054            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_Link5;
    7055            0 :                         break;
    7056            0 :                 case DTC_Link_CFO:
    7057            0 :                         reg = DTC_Register_SERDES_RXPRBSErrorCount_CFOLink;
    7058            0 :                         break;
    7059            0 :                 default: {
    7060            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7061            0 :                         __SS_THROW__;
    7062            0 :                 }
    7063              :         }
    7064            0 :         WriteRegister_(1, reg);
    7065            0 : }
    7066              : 
    7067            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink0()
    7068              : {
    7069            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link0);
    7070            0 :         form.description = "SERDES RX PRBS Error Count Link 0";
    7071            0 :         std::stringstream o;
    7072            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_0, form.value);
    7073            0 :         form.vals.push_back(o.str());
    7074            0 :         return form;
    7075            0 : }
    7076            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink1()
    7077              : {
    7078            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link1);
    7079            0 :         form.description = "SERDES RX PRBS Error Count Link 1";
    7080            0 :         std::stringstream o;
    7081            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_1, form.value);
    7082            0 :         form.vals.push_back(o.str());
    7083            0 :         return form;
    7084            0 : }
    7085            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink2()
    7086              : {
    7087            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link2);
    7088            0 :         form.description = "SERDES RX PRBS Error Count Link 2";
    7089            0 :         std::stringstream o;
    7090            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_2, form.value);
    7091            0 :         form.vals.push_back(o.str());
    7092            0 :         return form;
    7093            0 : }
    7094            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink3()
    7095              : {
    7096            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link3);
    7097            0 :         form.description = "SERDES RX PRBS Error Count Link 3";
    7098            0 :         std::stringstream o;
    7099            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_3, form.value);
    7100            0 :         form.vals.push_back(o.str());
    7101            0 :         return form;
    7102            0 : }
    7103            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink4()
    7104              : {
    7105            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link4);
    7106            0 :         form.description = "SERDES RX PRBS Error Count Link 4";
    7107            0 :         std::stringstream o;
    7108            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_4, form.value);
    7109            0 :         form.vals.push_back(o.str());
    7110            0 :         return form;
    7111            0 : }
    7112            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountLink5()
    7113              : {
    7114            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_Link5);
    7115            0 :         form.description = "SERDES RX PRBS Error Count Link 5";
    7116            0 :         std::stringstream o;
    7117            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_5, form.value);
    7118            0 :         form.vals.push_back(o.str());
    7119            0 :         return form;
    7120            0 : }
    7121            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXPRBSErrorCountCFOLink()
    7122              : {
    7123            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXPRBSErrorCount_CFOLink);
    7124            0 :         form.description = "SERDES RX PRBS Error Count CFO Link";
    7125            0 :         std::stringstream o;
    7126            0 :         o << std::dec << ReadSERDESRXPRBSErrorCount(DTC_Link_CFO, form.value);
    7127            0 :         form.vals.push_back(o.str());
    7128            0 :         return form;
    7129            0 : }
    7130              : 
    7131            0 : uint32_t DTCLib::DTC_Registers::ReadSERDESRXCRCErrorCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7132              : {
    7133              :         DTC_Register reg;
    7134            0 :         switch (link)
    7135              :         {
    7136            0 :                 case DTC_Link_0:
    7137            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
    7138            0 :                         break;
    7139            0 :                 case DTC_Link_1:
    7140            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
    7141            0 :                         break;
    7142            0 :                 case DTC_Link_2:
    7143            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
    7144            0 :                         break;
    7145            0 :                 case DTC_Link_3:
    7146            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
    7147            0 :                         break;
    7148            0 :                 case DTC_Link_4:
    7149            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
    7150            0 :                         break;
    7151            0 :                 case DTC_Link_5:
    7152            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
    7153            0 :                         break;
    7154            0 :                 case DTC_Link_CFO:
    7155            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
    7156            0 :                         break;
    7157            0 :                 default: {
    7158            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7159            0 :                         __SS_THROW__;
    7160            0 :                 }
    7161              :         }
    7162            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    7163              : }
    7164            0 : void DTCLib::DTC_Registers::ClearSERDESRXCRCErrorCount(DTC_Link_ID const& link)
    7165              : {
    7166              :         DTC_Register reg;
    7167            0 :         switch (link)
    7168              :         {
    7169            0 :                 case DTC_Link_0:
    7170            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link0;
    7171            0 :                         break;
    7172            0 :                 case DTC_Link_1:
    7173            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link1;
    7174            0 :                         break;
    7175            0 :                 case DTC_Link_2:
    7176            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link2;
    7177            0 :                         break;
    7178            0 :                 case DTC_Link_3:
    7179            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link3;
    7180            0 :                         break;
    7181            0 :                 case DTC_Link_4:
    7182            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link4;
    7183            0 :                         break;
    7184            0 :                 case DTC_Link_5:
    7185            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_Link5;
    7186            0 :                         break;
    7187            0 :                 case DTC_Link_CFO:
    7188            0 :                         reg = DTC_Register_SERDES_RXCRCErrorCount_CFOLink;
    7189            0 :                         break;
    7190            0 :                 default: {
    7191            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7192            0 :                         __SS_THROW__;
    7193            0 :                 }
    7194              :         }
    7195            0 :         WriteRegister_(1, reg);
    7196            0 : }
    7197              : 
    7198            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink0()
    7199              : {
    7200            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link0);
    7201            0 :         form.description = "SERDES RX CRC Error Count Link 0";
    7202            0 :         std::stringstream o;
    7203            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_0, form.value);
    7204            0 :         form.vals.push_back(o.str());
    7205            0 :         return form;
    7206            0 : }
    7207            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink1()
    7208              : {
    7209            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link1);
    7210            0 :         form.description = "SERDES RX CRC Error Count Link 1";
    7211            0 :         std::stringstream o;
    7212            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_1, form.value);
    7213            0 :         form.vals.push_back(o.str());
    7214            0 :         return form;
    7215            0 : }
    7216            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink2()
    7217              : {
    7218            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link2);
    7219            0 :         form.description = "SERDES RX CRC Error Count Link 2";
    7220            0 :         std::stringstream o;
    7221            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_2, form.value);
    7222            0 :         form.vals.push_back(o.str());
    7223            0 :         return form;
    7224            0 : }
    7225            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink3()
    7226              : {
    7227            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link3);
    7228            0 :         form.description = "SERDES RX CRC Error Count Link 3";
    7229            0 :         std::stringstream o;
    7230            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_3, form.value);
    7231            0 :         form.vals.push_back(o.str());
    7232            0 :         return form;
    7233            0 : }
    7234            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink4()
    7235              : {
    7236            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link4);
    7237            0 :         form.description = "SERDES RX CRC Error Count Link 4";
    7238            0 :         std::stringstream o;
    7239            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_4, form.value);
    7240            0 :         form.vals.push_back(o.str());
    7241            0 :         return form;
    7242            0 : }
    7243            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountLink5()
    7244              : {
    7245            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_Link5);
    7246            0 :         form.description = "SERDES RX CRC Error Count Link 5";
    7247            0 :         std::stringstream o;
    7248            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_5, form.value);
    7249            0 :         form.vals.push_back(o.str());
    7250            0 :         return form;
    7251            0 : }
    7252            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorCountCFOLink()
    7253              : {
    7254            0 :         auto form = CreateFormatter(DTC_Register_SERDES_RXCRCErrorCount_CFOLink);
    7255            0 :         form.description = "SERDES RX CRC Error Count CFO Link";
    7256            0 :         std::stringstream o;
    7257            0 :         o << std::dec << ReadSERDESRXCRCErrorCount(DTC_Link_CFO, form.value);
    7258            0 :         form.vals.push_back(o.str());
    7259            0 :         return form;
    7260            0 : }
    7261              : 
    7262              : // SERDES RX CRC Error Control
    7263            0 : bool DTCLib::DTC_Registers::ReadEnableInduceSERDESRXCRCError(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7264              : {
    7265            0 :         auto dataSet = std::bitset<32>(val.has_value() ? *val : ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7266            0 :         return dataSet[link];
    7267              : }
    7268            0 : void DTCLib::DTC_Registers::EnableInduceSERDESRXCRCError(DTC_Link_ID const& link)
    7269              : {
    7270            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7271            0 :         dataSet[link] = 1;
    7272            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
    7273            0 : }
    7274            0 : void DTCLib::DTC_Registers::DisableInduceSERDESRXCRCError(DTC_Link_ID const& link)
    7275              : {
    7276            0 :         auto dataSet = std::bitset<32>(ReadRegister_(DTC_Register_SERDES_RXCRCErrorControl));
    7277            0 :         dataSet[link] = 0;
    7278            0 :         WriteRegister_(dataSet.to_ulong(), DTC_Register_SERDES_RXCRCErrorControl);
    7279            0 : }
    7280            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatSERDESRXCRCErrorControl()
    7281              : {
    7282            0 :         auto form = CreateFormatter(DTC_Register_SERDESTXRXInvertEnable);
    7283            0 :         form.description = "SERDES RX CRC Error Control";
    7284            0 :         form.vals.push_back("([ x = 1 (hi) ])");  // translation
    7285            0 :         for (auto r : DTC_ROC_Links)
    7286            0 :                 form.vals.push_back(std::string("Induce Error Link ") + std::to_string(r) + ":  [" +
    7287            0 :                                                         (ReadEnableInduceSERDESRXCRCError(r, form.value) ? "x" : " ") + "]");
    7288              : 
    7289            0 :         form.vals.push_back(std::string("Incude Error CFO Link: [") +
    7290            0 :                                                 (ReadEnableInduceSERDESRXCRCError(DTC_Link_CFO, form.value) ? "x" : " ") + "]");
    7291              : 
    7292            0 :         return form;
    7293            0 : }
    7294              : 
    7295            0 : uint32_t DTCLib::DTC_Registers::ReadEVBSERDESRXPacketErrorCounter(std::optional<uint32_t> val)
    7296              : {
    7297            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EBVSERDES_RXPacketErrorCount);
    7298              : }
    7299            0 : void DTCLib::DTC_Registers::ClearEVBSERDESRXPacketErrorCounter()
    7300              : {
    7301            0 :         WriteRegister_(1, DTC_Register_EBVSERDES_RXPacketErrorCount);
    7302            0 : }
    7303            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatEVBSERDESRXPacketErrorCounter()
    7304              : {
    7305            0 :         auto form = CreateFormatter(DTC_Register_EBVSERDES_RXPacketErrorCount);
    7306            0 :         form.description = "EVB SERDES RX Packet Error Counter";
    7307            0 :         std::stringstream o;
    7308            0 :         o << std::dec << ReadEVBSERDESRXPacketErrorCounter(form.value);
    7309            0 :         form.vals.push_back(o.str());
    7310            0 :         return form;
    7311            0 : }
    7312              : 
    7313              : // Jitter Attenuator SERDES RX Recovered Clock LOS Counter
    7314            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorRecoveredClockLOSCount(std::optional<uint32_t> val)
    7315              : {
    7316            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7317              : }
    7318            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorRecoveredClockLOSCount()
    7319              : {
    7320            0 :         WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7321            0 : }
    7322            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorRecoveredClockLOSCount()
    7323              : {
    7324            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount);
    7325            0 :         form.description = "Jitter Attenuator SERDES RX Recovered Clock LOS Counter";
    7326            0 :         std::stringstream o;
    7327            0 :         o << std::dec << ReadJitterAttenuatorRecoveredClockLOSCount(form.value);
    7328            0 :         form.vals.push_back(o.str());
    7329            0 :         return form;
    7330            0 : }
    7331              : 
    7332              : // Jitter Attenuator SERDES RX External Clock LOS Counter
    7333            0 : uint32_t DTCLib::DTC_Registers::ReadJitterAttenuatorExternalClockLOSCount(std::optional<uint32_t> val)
    7334              : {
    7335            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7336              : }
    7337            0 : void DTCLib::DTC_Registers::ClearJitterAttenuatorExternalClockLOSCount()
    7338              : {
    7339            0 :         WriteRegister_(1, DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7340            0 : }
    7341            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatJitterAttenuatorExternalClockLOSCount()
    7342              : {
    7343            0 :         auto form = CreateFormatter(DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount);
    7344            0 :         form.description = "Jitter Attenuator SERDES RX External Clock LOS Counter";
    7345            0 :         std::stringstream o;
    7346            0 :         o << std::dec << ReadJitterAttenuatorExternalClockLOSCount(form.value);
    7347            0 :         form.vals.push_back(o.str());
    7348            0 :         return form;
    7349            0 : }
    7350              : 
    7351              : // ROC Emulator Interpacket Delay
    7352            0 : uint32_t DTCLib::DTC_Registers::ReadROCEmulatorInterpacketDelay(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7353              : {
    7354              :         DTC_Register reg;
    7355            0 :         switch (link)
    7356              :         {
    7357            0 :                 case DTC_Link_0:
    7358            0 :                         reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
    7359            0 :                         break;
    7360              :                 // case DTC_Link_1:
    7361              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
    7362              :                 //      break;
    7363              :                 // case DTC_Link_2:
    7364              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
    7365              :                 //      break;
    7366              :                 // case DTC_Link_3:
    7367              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
    7368              :                 //      break;
    7369              :                 // case DTC_Link_4:
    7370              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
    7371              :                 //      break;
    7372              :                 // case DTC_Link_5:
    7373              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
    7374              :                 //      break;
    7375            0 :                 default: {
    7376            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7377            0 :                         __SS_THROW__;
    7378            0 :                 }
    7379              :         }
    7380            0 :         return val.has_value() ? *val : ReadRegister_(reg);
    7381              : }
    7382            0 : void DTCLib::DTC_Registers::SetROCEmulatorInterpacketDelay(DTC_Link_ID const& link, uint32_t delay)
    7383              : {
    7384              :         DTC_Register reg;
    7385            0 :         switch (link)
    7386              :         {
    7387            0 :                 case DTC_Link_0:
    7388            0 :                         reg = DTC_Register_ROCEmulator_InterpacketDelay_Link0;
    7389            0 :                         break;
    7390              :                 // case DTC_Link_1:
    7391              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link1;
    7392              :                 //      break;
    7393              :                 // case DTC_Link_2:
    7394              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link2;
    7395              :                 //      break;
    7396              :                 // case DTC_Link_3:
    7397              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link3;
    7398              :                 //      break;
    7399              :                 // case DTC_Link_4:
    7400              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link4;
    7401              :                 //      break;
    7402              :                 // case DTC_Link_5:
    7403              :                 //      reg = DTC_Register_ROCEmulator_InterpacketDelay_Link5;
    7404              :                 //      break;
    7405            0 :                 default: {
    7406            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7407            0 :                         __SS_THROW__;
    7408            0 :                 }
    7409              :         }
    7410            0 :         WriteRegister_(delay, reg);
    7411            0 : }
    7412            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink0()
    7413              : {
    7414            0 :         auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link0);
    7415            0 :         form.description = "ROC Emulator Interpacket Delay all Links (*5ns)";
    7416            0 :         std::stringstream o;
    7417            0 :         o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_0, form.value);
    7418            0 :         form.vals.push_back(o.str());
    7419            0 :         return form;
    7420            0 : }
    7421              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink1()
    7422              : // {
    7423              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link1);
    7424              : //      form.description = "ROC Emulator Interpacket Delay Link 1 (*5ns)";
    7425              : //      std::stringstream o;
    7426              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_1, form.value);
    7427              : //      form.vals.push_back(o.str());
    7428              : //      return form;
    7429              : // }
    7430              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink2()
    7431              : // {
    7432              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link2);
    7433              : //      form.description = "ROC Emulator Interpacket Delay Link 2 (*5ns)";
    7434              : //      std::stringstream o;
    7435              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_2, form.value);
    7436              : //      form.vals.push_back(o.str());
    7437              : //      return form;
    7438              : // }
    7439              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink3()
    7440              : // {
    7441              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link3);
    7442              : //      form.description = "ROC Emulator Interpacket Delay Link 3 (*5ns)";
    7443              : //      std::stringstream o;
    7444              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_3, form.value);
    7445              : //      form.vals.push_back(o.str());
    7446              : //      return form;
    7447              : // }
    7448              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink4()
    7449              : // {
    7450              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link4);
    7451              : //      form.description = "ROC Emulator Interpacket Delay Link 4 (*5ns)";
    7452              : //      std::stringstream o;
    7453              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_4, form.value);
    7454              : //      form.vals.push_back(o.str());
    7455              : //      return form;
    7456              : // }
    7457              : // DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatROCEmulatorInterpacketDelayLink5()
    7458              : // {
    7459              : //      auto form = CreateFormatter(DTC_Register_ROCEmulator_InterpacketDelay_Link5);
    7460              : //      form.description = "ROC Emulator Interpacket Delay Link 5 (*5ns)";
    7461              : //      std::stringstream o;
    7462              : //      o << std::dec << ReadROCEmulatorInterpacketDelay(DTC_Link_5, form.value);
    7463              : //      form.vals.push_back(o.str());
    7464              : //      return form;
    7465              : // }
    7466              : 
    7467              : // TX Data Request Packet Count
    7468            0 : uint32_t DTCLib::DTC_Registers::ReadTXEventWindowMarkerCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7469              : {
    7470            0 :         return val.has_value() ? *val : ReadRegister_(GetTXEventWindowMarkerCountLinkRegister(link));
    7471              : }  // end ReadTXEventWindowMarkerCount()
    7472              : 
    7473            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXEventWindowMarkerCountLink(DTC_Link_ID const& link)
    7474              : {
    7475            0 :         auto form = CreateFormatter(GetTXEventWindowMarkerCountLinkRegister(link));
    7476            0 :         if (link == DTC_Link_CFO)
    7477            0 :                 form.description = "CFO Event Window Marker (EWM) Count";
    7478              :         else
    7479            0 :                 form.description = "EWM TX Count on Link " +
    7480            0 :                                                    std::to_string((GetTXEventWindowMarkerCountLinkRegister(link) -
    7481            0 :                                                                                    GetTXEventWindowMarkerCountLinkRegister(DTC_Link_0)) /
    7482            0 :                                                                                   4);
    7483            0 :         std::stringstream o;
    7484            0 :         o << std::dec << ReadTXEventWindowMarkerCount(link, form.value);
    7485            0 :         form.vals.push_back(o.str());
    7486            0 :         return form;
    7487            0 : }  // end FormatTXEventWindowMarkerCountLink()
    7488              : 
    7489            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXEventWindowMarkerCountLinkRegister(DTC_Link_ID const& link)
    7490              : {
    7491              :         DTC_Register reg;
    7492            0 :         switch (link)
    7493              :         {
    7494            0 :                 case DTC_Link_0:
    7495            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link0;
    7496            0 :                         break;
    7497            0 :                 case DTC_Link_1:
    7498            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link1;
    7499            0 :                         break;
    7500            0 :                 case DTC_Link_2:
    7501            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link2;
    7502            0 :                         break;
    7503            0 :                 case DTC_Link_3:
    7504            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link3;
    7505            0 :                         break;
    7506            0 :                 case DTC_Link_4:
    7507            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link4;
    7508            0 :                         break;
    7509            0 :                 case DTC_Link_5:
    7510            0 :                         reg = DTC_Register_TXEventWindowMarkerCount_Link5;
    7511            0 :                         break;
    7512            0 :                 case DTC_Link_CFO:
    7513            0 :                         reg = DTC_Register_CFOTXEventWindowMarkerCount_Link6;
    7514            0 :                         break;
    7515            0 :                 default: {
    7516            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7517              :                         ss << "\n\nThe stack trace is as follows:\n"
    7518            0 :                            << otsStyleStackTrace() << __E__;
    7519            0 :                         __SS_THROW__;
    7520            0 :                 }
    7521              :         }
    7522            0 :         return reg;
    7523              : }  // end GetTXEventWindowMarkerCountLinkRegister()
    7524              : 
    7525              : // TX Null Heartbeat Packet Count
    7526              : // Receive DH Timeout Count
    7527            0 : uint32_t DTCLib::DTC_Registers::ReadReceiveDHTimeoutCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7528              : {
    7529            0 :         return val.has_value() ? *val : ReadRegister_(GetReceiveDHTimeoutCountLinkRegister(link));
    7530              : }  // end ReadReceiveDHTimeoutCount()
    7531              : 
    7532            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetReceiveDHTimeoutCountLinkRegister(DTC_Link_ID const& link)
    7533              : {
    7534              :         DTC_Register reg;
    7535            0 :         switch (link)
    7536              :         {
    7537            0 :                 case DTC_Link_0:
    7538            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link0;
    7539            0 :                         break;
    7540            0 :                 case DTC_Link_1:
    7541            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link1;
    7542            0 :                         break;
    7543            0 :                 case DTC_Link_2:
    7544            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link2;
    7545            0 :                         break;
    7546            0 :                 case DTC_Link_3:
    7547            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link3;
    7548            0 :                         break;
    7549            0 :                 case DTC_Link_4:
    7550            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link4;
    7551            0 :                         break;
    7552            0 :                 case DTC_Link_5:
    7553            0 :                         reg = DTC_Register_ReceiveDHTimeoutCount_Link5;
    7554            0 :                         break;
    7555            0 :                 default: {
    7556            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7557            0 :                         __SS_THROW__;
    7558            0 :                 }
    7559              :         }
    7560            0 :         return reg;
    7561              : }  // end GetReceiveDHTimeoutCountLinkRegister()
    7562              : 
    7563            0 : uint32_t DTCLib::DTC_Registers::ReadTXNullHeartbeatCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7564              : {
    7565            0 :         return val.has_value() ? *val : ReadRegister_(GetTXNullHeartbeatCountLinkRegister(link));
    7566              : }  // end ReadTXNullHeartbeatCount()
    7567              : 
    7568            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXNullHeartbeatCountLink(DTC_Link_ID const& link)
    7569              : {
    7570            0 :         auto form = CreateFormatter(GetTXNullHeartbeatCountLinkRegister(link));
    7571            0 :         form.description = "Tx Null HBPs on Link " +
    7572            0 :                                            std::to_string((GetTXNullHeartbeatCountLinkRegister(link) -
    7573            0 :                                                                            GetTXNullHeartbeatCountLinkRegister(DTC_Link_0)) /
    7574            0 :                                                                           4);
    7575            0 :         std::stringstream o;
    7576            0 :         o << std::dec << ReadTXNullHeartbeatCount(link, form.value);
    7577            0 :         form.vals.push_back(o.str());
    7578            0 :         return form;
    7579            0 : }  // end FormatTXNullHeartbeatCountLink()
    7580              : 
    7581            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXNullHeartbeatCountLinkRegister(DTC_Link_ID const& link)
    7582              : {
    7583              :         DTC_Register reg;
    7584            0 :         switch (link)
    7585              :         {
    7586            0 :                 case DTC_Link_0:
    7587            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link0;
    7588            0 :                         break;
    7589            0 :                 case DTC_Link_1:
    7590            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link1;
    7591            0 :                         break;
    7592            0 :                 case DTC_Link_2:
    7593            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link2;
    7594            0 :                         break;
    7595            0 :                 case DTC_Link_3:
    7596            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link3;
    7597            0 :                         break;
    7598            0 :                 case DTC_Link_4:
    7599            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link4;
    7600            0 :                         break;
    7601            0 :                 case DTC_Link_5:
    7602            0 :                         reg = DTC_Register_TXNullHeartbeatCount_Link5;
    7603            0 :                         break;
    7604            0 :                 default: {
    7605            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7606              :                         ss << "\n\nThe stack trace is as follows:\n"
    7607            0 :                            << otsStyleStackTrace() << __E__;
    7608            0 :                         __SS_THROW__;
    7609            0 :                 }
    7610              :         }
    7611            0 :         return reg;
    7612              : }  // end GetTXNullHeartbeatCountLinkRegister()
    7613              : 
    7614              : // TX Blocked (Suppressed) Heartbeat Count
    7615            0 : uint32_t DTCLib::DTC_Registers::ReadTXBlockedHeartbeatCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7616              : {
    7617            0 :         return val.has_value() ? *val : ReadRegister_(GetTXBlockedHeartbeatCountLinkRegister(link));
    7618              : }  // end ReadTXBlockedHeartbeatCount()
    7619              : 
    7620            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXBlockedHeartbeatCountLink(DTC_Link_ID const& link)
    7621              : {
    7622            0 :         auto form = CreateFormatter(GetTXBlockedHeartbeatCountLinkRegister(link));
    7623            0 :         form.description = "Tx Blocked HBPs on Link " +
    7624            0 :                                            std::to_string((GetTXBlockedHeartbeatCountLinkRegister(link) -
    7625            0 :                                                                            GetTXBlockedHeartbeatCountLinkRegister(DTC_Link_0)) /
    7626            0 :                                                                           4);
    7627            0 :         std::stringstream o;
    7628            0 :         o << std::dec << ReadTXBlockedHeartbeatCount(link, form.value);
    7629            0 :         form.vals.push_back(o.str());
    7630            0 :         return form;
    7631            0 : }  // end FormatTXBlockedHeartbeatCountLink()
    7632              : 
    7633            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXBlockedHeartbeatCountLinkRegister(DTC_Link_ID const& link)
    7634              : {
    7635              :         DTC_Register reg;
    7636            0 :         switch (link)
    7637              :         {
    7638            0 :                 case DTC_Link_0:
    7639            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link0;
    7640            0 :                         break;
    7641            0 :                 case DTC_Link_1:
    7642            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link1;
    7643            0 :                         break;
    7644            0 :                 case DTC_Link_2:
    7645            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link2;
    7646            0 :                         break;
    7647            0 :                 case DTC_Link_3:
    7648            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link3;
    7649            0 :                         break;
    7650            0 :                 case DTC_Link_4:
    7651            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link4;
    7652            0 :                         break;
    7653            0 :                 case DTC_Link_5:
    7654            0 :                         reg = DTC_Register_TXBlockedHeartbeatCount_Link5;
    7655            0 :                         break;
    7656            0 :                 default: {
    7657            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7658              :                         ss << "\n\nThe stack trace is as follows:\n"
    7659            0 :                            << otsStyleStackTrace() << __E__;
    7660            0 :                         __SS_THROW__;
    7661            0 :                 }
    7662              :         }
    7663            0 :         return reg;
    7664              : }  // end GetTXBlockedHeartbeatCountLinkRegister()
    7665              : 
    7666              : // TX Non-null Heartbeat Count
    7667            0 : uint32_t DTCLib::DTC_Registers::ReadTXNonnullHeartbeatCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7668              : {
    7669            0 :         return val.has_value() ? *val : ReadRegister_(GetTXNonnullHeartbeatCountLinkRegister(link));
    7670              : }  // end ReadTXNonnullHeartbeatCount()
    7671              : 
    7672            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXNonnullHeartbeatCountLink(DTC_Link_ID const& link)
    7673              : {
    7674            0 :         auto form = CreateFormatter(GetTXNonnullHeartbeatCountLinkRegister(link));
    7675            0 :         form.description = "Tx Non-null HBPs on Link " +
    7676            0 :                                            std::to_string((GetTXNonnullHeartbeatCountLinkRegister(link) -
    7677            0 :                                                                            GetTXNonnullHeartbeatCountLinkRegister(DTC_Link_0)) /
    7678            0 :                                                                           4);
    7679            0 :         std::stringstream o;
    7680            0 :         o << std::dec << ReadTXNonnullHeartbeatCount(link, form.value);
    7681            0 :         form.vals.push_back(o.str());
    7682            0 :         return form;
    7683            0 : }  // end FormatTXNonnullHeartbeatCountLink()
    7684              : 
    7685            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXNonnullHeartbeatCountLinkRegister(DTC_Link_ID const& link)
    7686              : {
    7687              :         DTC_Register reg;
    7688            0 :         switch (link)
    7689              :         {
    7690            0 :                 case DTC_Link_0:
    7691            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link0;
    7692            0 :                         break;
    7693            0 :                 case DTC_Link_1:
    7694            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link1;
    7695            0 :                         break;
    7696            0 :                 case DTC_Link_2:
    7697            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link2;
    7698            0 :                         break;
    7699            0 :                 case DTC_Link_3:
    7700            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link3;
    7701            0 :                         break;
    7702            0 :                 case DTC_Link_4:
    7703            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link4;
    7704            0 :                         break;
    7705            0 :                 case DTC_Link_5:
    7706            0 :                         reg = DTC_Register_TXNonnullHeartbeatCount_Link5;
    7707            0 :                         break;
    7708            0 :                 default: {
    7709            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7710              :                         ss << "\n\nThe stack trace is as follows:\n"
    7711            0 :                            << otsStyleStackTrace() << __E__;
    7712            0 :                         __SS_THROW__;
    7713            0 :                 }
    7714              :         }
    7715            0 :         return reg;
    7716              : }  // end GetTXNonnullHeartbeatCountLinkRegister()
    7717              : 
    7718              : // TX Data Request Packet Count
    7719            0 : uint32_t DTCLib::DTC_Registers::ReadTXDataRequestPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7720              : {
    7721            0 :         return val.has_value() ? *val : ReadRegister_(GetTXDataRequestPacketCountLinkRegister(link));
    7722              : }  // end ReadTXDataRequestPacketCount()
    7723              : 
    7724            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXDataRequestPacketCountLink(DTC_Link_ID const& link)
    7725              : {
    7726            0 :         auto form = CreateFormatter(GetTXDataRequestPacketCountLinkRegister(link));
    7727            0 :         form.description = "DRP TX Count on Link " +
    7728            0 :                                            std::to_string((GetTXDataRequestPacketCountLinkRegister(link) -
    7729            0 :                                                                            GetTXDataRequestPacketCountLinkRegister(DTC_Link_0)) /
    7730            0 :                                                                           4);
    7731            0 :         std::stringstream o;
    7732            0 :         o << std::dec << ReadTXDataRequestPacketCount(link, form.value);
    7733            0 :         form.vals.push_back(o.str());
    7734            0 :         return form;
    7735            0 : }  // end FormatTXEventWindowMarkerCountLink()
    7736              : 
    7737            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXDataRequestPacketCountLinkRegister(DTC_Link_ID const& link)
    7738              : {
    7739              :         DTC_Register reg;
    7740            0 :         switch (link)
    7741              :         {
    7742            0 :                 case DTC_Link_0:
    7743            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link0;
    7744            0 :                         break;
    7745            0 :                 case DTC_Link_1:
    7746            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link1;
    7747            0 :                         break;
    7748            0 :                 case DTC_Link_2:
    7749            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link2;
    7750            0 :                         break;
    7751            0 :                 case DTC_Link_3:
    7752            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link3;
    7753            0 :                         break;
    7754            0 :                 case DTC_Link_4:
    7755            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link4;
    7756            0 :                         break;
    7757            0 :                 case DTC_Link_5:
    7758            0 :                         reg = DTC_Register_TXDataRequestPacketCount_Link5;
    7759            0 :                         break;
    7760            0 :                 default: {
    7761            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7762              :                         ss << "\n\nThe stack trace is as follows:\n"
    7763            0 :                            << otsStyleStackTrace() << __E__;
    7764            0 :                         __SS_THROW__;
    7765            0 :                 }
    7766              :         }
    7767            0 :         return reg;
    7768              : }  // end GetTXDataRequestPacketCountLinkRegister()
    7769              : 
    7770            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOTXClockMarkerCountLink6()
    7771              : {
    7772            0 :         auto form = CreateFormatter(DTC_Register_CFOTXClockMarkerCount_Link6);
    7773            0 :         form.description = "CFO Clock Marker Count";
    7774            0 :         std::stringstream o;
    7775            0 :         o << std::dec << ReadCFOTXClockMarkerCountLink6(form.value);
    7776            0 :         form.vals.push_back(o.str());
    7777            0 :         return form;
    7778            0 : }  // end FormatCFOTXClockMarkerCountLink6()
    7779              : 
    7780            0 : uint32_t DTCLib::DTC_Registers::ReadCFOTXClockMarkerCountLink6(std::optional<uint32_t> val)
    7781              : {
    7782            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOTXClockMarkerCount_Link6);
    7783              : }  // end ReadCFOTXClockMarkerCountLink6()
    7784              : 
    7785              : // TX Heartbeat Packet Count
    7786            0 : uint32_t DTCLib::DTC_Registers::ReadTXHeartbeatPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7787              : {
    7788            0 :         return val.has_value() ? *val : ReadRegister_(GetTXHeartbeatPacketCountLinkRegister(link));
    7789              : }  // end ReadTXHeartbeatPacketCount()
    7790            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatTXHeartbeatPacketCountLink(DTC_Link_ID const& link)
    7791              : {
    7792            0 :         auto form = CreateFormatter(GetTXHeartbeatPacketCountLinkRegister(link));
    7793            0 :         if (link == DTC_Link_CFO)
    7794            0 :                 form.description = "CFO Heartbeat Packet (HBP) Count";
    7795              :         else
    7796            0 :                 form.description = "HBP TX Counter Link " +
    7797            0 :                                                    std::to_string((GetTXHeartbeatPacketCountLinkRegister(link) -
    7798            0 :                                                                                    GetTXHeartbeatPacketCountLinkRegister(DTC_Link_0)) /
    7799            0 :                                                                                   4);
    7800            0 :         std::stringstream o;
    7801            0 :         o << std::dec << ReadTXHeartbeatPacketCount(DTC_Link_0, form.value);
    7802            0 :         form.vals.push_back(o.str());
    7803            0 :         return form;
    7804            0 : }  // end FormatTXHeartbeatPacketCountLink()
    7805              : 
    7806            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetTXHeartbeatPacketCountLinkRegister(DTC_Link_ID const& link)
    7807              : {
    7808              :         DTC_Register reg;
    7809            0 :         switch (link)
    7810              :         {
    7811            0 :                 case DTC_Link_0:
    7812            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link0;
    7813            0 :                         break;
    7814            0 :                 case DTC_Link_1:
    7815            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link1;
    7816            0 :                         break;
    7817            0 :                 case DTC_Link_2:
    7818            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link2;
    7819            0 :                         break;
    7820            0 :                 case DTC_Link_3:
    7821            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link3;
    7822            0 :                         break;
    7823            0 :                 case DTC_Link_4:
    7824            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link4;
    7825            0 :                         break;
    7826            0 :                 case DTC_Link_5:
    7827            0 :                         reg = DTC_Register_TXHeartbeatPacketCount_Link5;
    7828            0 :                         break;
    7829            0 :                 case DTC_Link_CFO:
    7830            0 :                         reg = DTC_Register_CFOTXHeartbeatPacketCount_Link5;
    7831            0 :                         break;
    7832            0 :                 default: {
    7833            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7834            0 :                         __SS_THROW__;
    7835            0 :                 }
    7836              :         }
    7837            0 :         return reg;
    7838              : }  // end GetTXHeartbeatPacketCountLinkRegister()
    7839              : 
    7840              : // RX Data Header Packet Count
    7841            0 : uint32_t DTCLib::DTC_Registers::ReadRXDataHeaderPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    7842              : {
    7843            0 :         return val.has_value() ? *val : ReadRegister_(GetRXDataHeaderPacketCountLinkRegister(link));
    7844              : }  // end ReadRXDataHeaderPacketCount()
    7845              : 
    7846            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataHeaderPacketCountLink(DTC_Link_ID const& link)
    7847              : {
    7848            0 :         auto form = CreateFormatter(GetRXDataHeaderPacketCountLinkRegister(link));
    7849            0 :         form.description = "ROC DH RX Count on Link " +
    7850            0 :                                            std::to_string((GetRXDataHeaderPacketCountLinkRegister(link) -
    7851            0 :                                                                            GetRXDataHeaderPacketCountLinkRegister(DTC_Link_0)) /
    7852            0 :                                                                           4);
    7853            0 :         std::stringstream o;
    7854            0 :         o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
    7855            0 :         form.vals.push_back(o.str());
    7856            0 :         return form;
    7857            0 : }  // end FormatRXDataHeaderPacketCountLink()
    7858              : 
    7859            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataHeaderPacketCountLinkRegister(DTC_Link_ID const& link)
    7860              : {
    7861              :         DTC_Register reg;
    7862            0 :         switch (link)
    7863              :         {
    7864            0 :                 case DTC_Link_0:
    7865            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link0;
    7866            0 :                         break;
    7867            0 :                 case DTC_Link_1:
    7868            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link1;
    7869            0 :                         break;
    7870            0 :                 case DTC_Link_2:
    7871            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link2;
    7872            0 :                         break;
    7873            0 :                 case DTC_Link_3:
    7874            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link3;
    7875            0 :                         break;
    7876            0 :                 case DTC_Link_4:
    7877            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link4;
    7878            0 :                         break;
    7879            0 :                 case DTC_Link_5:
    7880            0 :                         reg = DTC_Register_RXDataHeaderPacketCount_Link5;
    7881            0 :                         break;
    7882            0 :                 default: {
    7883            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    7884            0 :                         __SS_THROW__;
    7885            0 :                 }
    7886              :         }
    7887            0 :         return reg;
    7888              : }  // end GetRXDataHeaderPacketCountLinkRegister()
    7889              : 
    7890              : // CFO CDC Diagnostic (Parity Mismatch & Batch Slip Counts)
    7891            0 : uint32_t DTCLib::DTC_Registers::ReadCFOCDCDiag(std::optional<uint32_t> val)
    7892              : {
    7893            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_CFOCDCDiag);
    7894              : }
    7895              : 
    7896            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatCFOCDCDiag()
    7897              : {
    7898            0 :         auto form = CreateFormatter(DTC_Register_CFOCDCDiag);
    7899            0 :         form.description = "CFO CDC Diagnostic";
    7900            0 :         uint32_t parityMismatchCount = (form.value >> 16) & 0xFFFF;
    7901            0 :         uint32_t batchSlipCount = form.value & 0xFFFF;
    7902            0 :         form.vals.push_back(std::string("Parity Mismatch Count: ") + std::to_string(parityMismatchCount));
    7903            0 :         form.vals.push_back(std::string("Batch Slip Count:      ") + std::to_string(batchSlipCount));
    7904            0 :         return form;
    7905            0 : }
    7906              : 
    7907              : // EVB High Level Counters (0x9200/0x9204/0x9208), each holding two 16-bit word counters
    7908              : /// @brief Read the EVB firmware version from 0x9200 [15:0].
    7909              : ///        Encoded as 0xTMmm where T is type (B = EVBuilding), M is major, mm is minor.
    7910            0 : std::string DTCLib::DTC_Registers::ReadEVBFirmwareVersion(std::optional<uint32_t> val)
    7911              : {
    7912            0 :         uint32_t reg = val.has_value() ? *val : ReadRegister_(CFOandDTC_Register_DesignVersion);
    7913            0 :         uint16_t ver = reg & 0xFFFF;
    7914            0 :         char type = static_cast<char>((ver >> 12) & 0xF);
    7915            0 :         int major = (ver >> 8) & 0xF;
    7916            0 :         int minor = ver & 0xFF;
    7917            0 :         std::ostringstream o;
    7918            0 :         o << std::hex << std::uppercase << type << std::dec << major << "." << std::setw(2) << std::setfill('0') << minor;
    7919            0 :         return o.str();
    7920            0 : }  // end ReadEVBFirmwareVersion()
    7921              : 
    7922              : /// @brief Override to append EVB firmware version to the time-alive line when present.
    7923            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatDeviceTimeAlive()
    7924              : {
    7925            0 :         auto form = CFOandDTC_Registers::FormatDeviceTimeAlive();
    7926            0 :         uint32_t designVer = ReadRegister_(CFOandDTC_Register_DesignVersion);
    7927            0 :         uint8_t typeNibble = (designVer >> 12) & 0xF;
    7928            0 :         if (typeNibble == 0xB)  // 'B' = EVB firmware present
    7929              :         {
    7930            0 :                 auto& line = form.vals.back();
    7931            0 :                 auto pos = line.find("-ROC");
    7932            0 :                 if (pos == std::string::npos)
    7933            0 :                         pos = line.find("-Links");
    7934            0 :                 if (pos != std::string::npos)
    7935              :                 {
    7936            0 :                         while (pos > 0 && line[pos - 1] != ' ')
    7937            0 :                                 --pos;
    7938            0 :                         line.insert(pos, "EVB ");
    7939              :                 }
    7940              :                 else
    7941            0 :                         line += ", EVB";
    7942              :         }
    7943            0 :         return form;
    7944            0 : }  // end DTC_Registers::FormatDeviceTimeAlive()
    7945              : 
    7946            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters0(std::optional<uint32_t> val)
    7947              : {
    7948            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters0);
    7949              : }  // end ReadEVBHighLevelCounters0()
    7950              : 
    7951            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters1(std::optional<uint32_t> val)
    7952              : {
    7953            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters1);
    7954              : }  // end ReadEVBHighLevelCounters1()
    7955              : 
    7956            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters2(std::optional<uint32_t> val)
    7957              : {
    7958            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters2);
    7959              : }  // end ReadEVBHighLevelCounters2()
    7960              : 
    7961            0 : uint32_t DTCLib::DTC_Registers::ReadEVBHighLevelCounters3(std::optional<uint32_t> val)
    7962              : {
    7963            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBHighLevelCounters3);
    7964              : }  // end ReadEVBHighLevelCounters3()
    7965              : 
    7966            0 : uint16_t DTCLib::DTC_Registers::ReadEVBLocalChunkCap(std::optional<uint32_t> val)
    7967              : {
    7968            0 :         return static_cast<uint16_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBLocalChunkCap)) & 0xFFFFu);
    7969              : }  // end ReadEVBLocalChunkCap()
    7970              : 
    7971            0 : void DTCLib::DTC_Registers::SetEVBLocalChunkCap(uint16_t words)
    7972              : {
    7973            0 :         const uint32_t upperHalf = ReadRegister_(DTC_Register_EVBLocalChunkCap) & 0xFFFF0000u;
    7974            0 :         WriteRegister_(upperHalf | words, DTC_Register_EVBLocalChunkCap);
    7975            0 : }  // end SetEVBLocalChunkCap()
    7976              : 
    7977            0 : uint32_t DTCLib::DTC_Registers::ReadEVBRemoteChunkControl(std::optional<uint32_t> val)
    7978              : {
    7979            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBRemoteChunkControl);
    7980              : }  // end ReadEVBRemoteChunkControl()
    7981              : 
    7982            0 : void DTCLib::DTC_Registers::SetEVBRemoteChunkControl(uint32_t value)
    7983              : {
    7984            0 :         WriteRegister_(value, DTC_Register_EVBRemoteChunkControl);
    7985            0 : }  // end SetEVBRemoteChunkControl()
    7986              : 
    7987            0 : DTCLib::DTC_Registers::EVBTxHistoryEntry DTCLib::DTC_Registers::DecodeEVBTxHistoryEntry(uint32_t raw)
    7988              : {
    7989            0 :         EVBTxHistoryEntry entry;
    7990            0 :         entry.raw = raw;
    7991            0 :         entry.firstOfSubevent = (raw >> 28) & 1u;
    7992            0 :         entry.lastOfSubevent = (raw >> 27) & 1u;
    7993            0 :         entry.hasData = (raw >> 26) & 1u;
    7994            0 :         entry.destinationOffset = static_cast<uint8_t>((raw >> 21) & 0x1Fu);
    7995            0 :         entry.sequence = static_cast<uint8_t>((raw >> 13) & 0xFFu);
    7996            0 :         entry.sizeWords = static_cast<uint16_t>(raw & 0x1FFFu);
    7997            0 :         return entry;
    7998              : }  // end DecodeEVBTxHistoryEntry()
    7999              : 
    8000            0 : uint32_t DTCLib::DTC_Registers::ReadEVBTxHistoryStatus(std::optional<uint32_t> val)
    8001              : {
    8002            0 :         return val.has_value() ? *val : ReadRegister_(DTC_Register_EVBTxHistoryStatus);
    8003              : }  // end ReadEVBTxHistoryStatus()
    8004              : 
    8005            0 : uint16_t DTCLib::DTC_Registers::ReadEVBRxIllegalDestCount(std::optional<uint32_t> val)
    8006              : {
    8007            0 :         return static_cast<uint16_t>((val.has_value() ? *val : ReadRegister_(DTC_Register_EVBRxIllegalDestCount)) & 0xFFFFu);
    8008              : }  // end ReadEVBRxIllegalDestCount()
    8009              : 
    8010            0 : DTCLib::DTC_Registers::EVBTxHistory DTCLib::DTC_Registers::ReadEVBTxHistory(bool readEntries)
    8011              : {
    8012            0 :         EVBTxHistory history;
    8013            0 :         history.statusRaw = ReadEVBTxHistoryStatus();
    8014            0 :         history.frozen = (history.statusRaw >> 31) & 1u;
    8015            0 :         history.firstResendDestination = static_cast<uint8_t>((history.statusRaw >> 26) & 0x1Fu);
    8016            0 :         history.peerLastAckSequence = static_cast<uint8_t>((history.statusRaw >> 18) & 0xFFu);
    8017            0 :         history.entriesWritten = static_cast<uint16_t>(history.statusRaw & 0x3FFu);
    8018            0 :         history.ringWrapped = history.entriesWritten >= 1023;
    8019            0 :         if (!readEntries || history.entriesWritten == 0)
    8020            0 :                 return history;
    8021              :         // first read loads the output register; the next entriesWritten reads return entries 0..count-1.
    8022              :         // The pointer only rewinds on SoftReset: a first read of 0xFFFFFFFF means the log was already walked.
    8023            0 :         if (ReadRegister_(DTC_Register_EVBTxHistoryRead) == 0xFFFFFFFFu)
    8024              :         {
    8025            0 :                 history.alreadyWalked = true;
    8026            0 :                 return history;
    8027              :         }
    8028            0 :         history.entries.reserve(history.entriesWritten);
    8029            0 :         for (uint16_t index = 0; index < history.entriesWritten; ++index)
    8030              :         {
    8031            0 :                 const uint32_t raw = ReadRegister_(DTC_Register_EVBTxHistoryRead);
    8032            0 :                 if (raw == 0xFFFFFFFFu)
    8033              :                 {
    8034            0 :                         history.endMarkerSeen = true;
    8035            0 :                         break;
    8036              :                 }
    8037            0 :                 history.entries.push_back(DecodeEVBTxHistoryEntry(raw));
    8038              :         }
    8039            0 :         return history;
    8040            0 : }  // end ReadEVBTxHistory()
    8041              : 
    8042            0 : std::string DTCLib::DTC_Registers::FormatEVBTxHistoryText(const EVBTxHistory& history, const std::string& indent, size_t windowEntries)
    8043              : {
    8044            0 :         std::ostringstream o;
    8045            0 :         o << indent << "0x925C = 0x" << std::hex << std::setw(8) << std::setfill('0') << history.statusRaw << std::dec << std::setfill(' ')
    8046            0 :           << ": " << (history.frozen ? "FROZEN (a peer requested a retransmission; log stopped)" : "recording (no retransmission requested since SoftReset)")
    8047            0 :           << ", entries written " << history.entriesWritten;
    8048            0 :         if (history.frozen)
    8049            0 :                 o << ", first resend request from dest offset " << static_cast<int>(history.firstResendDestination)
    8050            0 :                   << ", peer last-acked seq 0x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>(history.peerLastAckSequence)
    8051            0 :                   << std::dec << std::setfill(' ');
    8052            0 :         if (history.ringWrapped)
    8053            0 :                 o << " (ring full: entries start at the oldest surviving packet, the last entry is the one just before the freeze)";
    8054            0 :         o << "\n";
    8055            0 :         if (history.alreadyWalked)
    8056              :         {
    8057            0 :                 o << indent << "entries already walked this run (0x91F0 returns 0xFFFFFFFF until the next SoftReset)\n";
    8058            0 :                 return o.str();
    8059              :         }
    8060            0 :         if (history.entries.empty())
    8061              :         {
    8062            0 :                 if (history.frozen && history.entriesWritten)
    8063            0 :                         o << indent << "(entries not read)\n";
    8064            0 :                 return o.str();
    8065              :         }
    8066              :         // locate the last-acked packet in the log; show a window ending a few entries past it (the dropped
    8067              :         // packet is the one after the last ack toward that destination)
    8068            0 :         size_t anchor = history.entries.size();
    8069            0 :         for (size_t index = history.entries.size(); index-- > 0;)
    8070            0 :                 if (history.entries[index].sequence == history.peerLastAckSequence &&
    8071            0 :                         (!history.frozen || history.entries[index].destinationOffset == history.firstResendDestination))
    8072              :                 {
    8073            0 :                         anchor = index;
    8074            0 :                         break;
    8075              :                 }
    8076              :         // Window: always include the final entry (in a frozen log it is the packet just before the freeze,
    8077              :         // which is the one the hw agent wants), and reach back far enough to show the acked packet when found.
    8078            0 :         const size_t last = history.entries.size();
    8079            0 :         size_t first = (last > windowEntries) ? last - windowEntries : 0;
    8080            0 :         if (anchor != history.entries.size() && anchor < first)
    8081            0 :                 first = (anchor > 2) ? anchor - 2 : 0;
    8082            0 :         o << indent << "final " << (last - first) << " of " << history.entries.size() << " entries"
    8083            0 :           << (anchor == history.entries.size() ? " (last-acked seq not found in log)" : " (last-acked packet marked <= ack)")
    8084            0 :           << (history.frozen ? "; the last row is the packet just before the freeze" : "") << "\n";
    8085              :         // The dropped candidate is the next packet toward the SAME destination as the acked one
    8086              :         // (sequence numbers are per destination, hw agent 2026-10-16), not simply the next log entry.
    8087            0 :         size_t droppedCandidate = history.entries.size();
    8088            0 :         if (history.frozen && anchor != history.entries.size())
    8089            0 :                 for (size_t index = anchor + 1; index < history.entries.size(); ++index)
    8090            0 :                         if (history.entries[index].destinationOffset == history.entries[anchor].destinationOffset)
    8091              :                         {
    8092            0 :                                 droppedCandidate = index;
    8093            0 :                                 break;
    8094              :                         }
    8095              :         // droppedCandidate, when found, is always below entries.size() == last, so it is inside the window
    8096            0 :         o << indent << "  idx   dest  seq   words  flags\n";
    8097            0 :         for (size_t index = first; index < last; ++index)
    8098              :         {
    8099            0 :                 const auto& entry = history.entries[index];
    8100            0 :                 o << indent << "  " << std::setw(4) << index << "  " << std::setw(4) << static_cast<int>(entry.destinationOffset) << "  0x" << std::hex
    8101            0 :                   << std::setw(2) << std::setfill('0') << static_cast<int>(entry.sequence) << std::dec << std::setfill(' ') << "  " << std::setw(5) << entry.sizeWords
    8102            0 :                   << "  " << (entry.hasData ? "data" : "null") << (entry.firstOfSubevent ? " first" : "") << (entry.lastOfSubevent ? " last" : "")
    8103              :                   << (index == anchor ? "  <= ack" : "") << (index == droppedCandidate ? "  <= next toward that dest: likely the dropped one" : "")
    8104            0 :                   << (history.frozen && index + 1 == last ? "  <= last before freeze" : "") << "\n";
    8105              :         }
    8106            0 :         if (history.endMarkerSeen)
    8107            0 :                 o << indent << "(end marker 0xFFFFFFFF reached before count entries)\n";
    8108            0 :         return o.str();
    8109            0 : }  // end FormatEVBTxHistoryText()
    8110              : 
    8111            0 : std::vector<uint32_t> DTCLib::DTC_Registers::ReadEVBStallCounters()
    8112              : {
    8113              :         static const DTC_Register stallRegisters[] = {
    8114              :                 DTC_Register_EVBStallTXCredit, DTC_Register_EVBStallTXWire, DTC_Register_EVBStallBufferManagerLocal,
    8115              :                 DTC_Register_EVBStallBufferManagerRemoteWait, DTC_Register_EVBStallDDRRead, DTC_Register_EVBStallROCHeld,
    8116              :                 DTC_Register_EVBStallTimebase, DTC_Register_EVBStallROCHeldPart1, DTC_Register_EVBStallROCHeldPart2,
    8117              :                 DTC_Register_EVBStallROCHeldPart3, DTC_Register_EVBStallROCHeldPart4, DTC_Register_EVBStallShare5,
    8118              :                 DTC_Register_EVBOutputHoldClocks, DTC_Register_EVBOutputLongestHold, DTC_Register_EVBOutputWordsAccepted};
    8119            0 :         std::vector<uint32_t> values;
    8120            0 :         for (auto stallRegister : stallRegisters)
    8121            0 :                 values.push_back(ReadRegister_(stallRegister));
    8122            0 :         return values;
    8123            0 : }  // end ReadEVBStallCounters()
    8124              : 
    8125              : namespace {
    8126              : /// Rows for the stall counters against the timebase (index 6 = 0x9228): clocks, ms (4 ns per
    8127              : /// clock) and share.  Indices 7-10 are the four parts of ROC-held time and must add up to index 5;
    8128              : /// index 11 is the fifth share (0x923C).  Shorter vectors (older bitfiles) print what they have.
    8129            0 : std::string formatEVBStallRows(const std::vector<uint64_t>& values, const std::string& indent, const std::string& timebaseLabel)
    8130              : {
    8131              :         static const char* const names[] = {
    8132              :                 "TX credit stall   (0x9210)", "TX wire busy      (0x9214)", "BM self chunk     (0x9218)",
    8133              :                 "BM remote waiting (0x921C)", "DDR read busy     (0x9220)", "ROC input held    (0x9224)",
    8134              :                 "timebase          (0x9228)",
    8135              :                 "ROC held part 1   (0x922C)", "ROC held part 2   (0x9230)", "ROC held part 3   (0x9234)",
    8136              :                 "ROC held part 4   (0x9238)", "DDR write busy    (0x923C)",
    8137              :                 "output hold       (0x9240)", "longest hold      (0x9244)", "words accepted    (0x9248)"};
    8138            0 :         const size_t timebaseIndex = 6;
    8139            0 :         const uint64_t timebase = values.size() > timebaseIndex ? values[timebaseIndex] : 0;
    8140            0 :         std::ostringstream o;
    8141            0 :         o << indent << "Timebase (0x9228): " << timebase << " clocks = " << std::fixed << std::setprecision(1)
    8142            0 :           << (timebase * 4.0e-6) << " ms " << timebaseLabel
    8143            0 :           << (timebase == 0 ? "  (zero: counters not in this bitfile or just reset)" : "") << "\n";
    8144            0 :         auto row = [&](size_t index) {
    8145            0 :                 if (index >= values.size()) return;
    8146            0 :                 o << indent << names[index] << ": " << std::setw(10) << values[index] << " clocks = " << std::setw(8) << std::setprecision(1)
    8147            0 :                   << (values[index] * 4.0e-6) << " ms";
    8148            0 :                 if (timebase)
    8149            0 :                         o << "  " << std::setw(5) << std::setprecision(1) << (100.0 * values[index] / timebase) << " %";
    8150            0 :                 o << "\n";
    8151            0 :         };
    8152            0 :         for (size_t index = 0; index < timebaseIndex; ++index) row(index);
    8153            0 :         if (values.size() > 11)
    8154              :         {
    8155            0 :                 for (size_t index = 7; index < 12; ++index) row(index);
    8156              :                 // the five registers are read one after another while they count, so a skew of a few
    8157              :                 // hundred clocks is the readout, not the firmware; 0x9224 itself must be matched to 1e-5
    8158            0 :                 const uint64_t heldPartsSum = values[7] + values[8] + values[9] + values[10];
    8159            0 :                 const uint64_t difference = heldPartsSum > values[5] ? heldPartsSum - values[5] : values[5] - heldPartsSum;
    8160            0 :                 const uint64_t tolerance = std::max<uint64_t>(10000, values[5] / 100000);
    8161            0 :                 o << indent << "ROC held parts 1-4 sum: " << heldPartsSum << " vs 0x9224 " << values[5] << "  "
    8162            0 :                   << (difference <= tolerance ? "OK" : "MISMATCH") << " (" << (heldPartsSum >= values[5] ? "+" : "-") << difference
    8163            0 :                   << " clocks, readout skew allowance " << tolerance << ")\n";
    8164              :         }
    8165            0 :         if (values.size() > 14)
    8166              :         {
    8167              :                 // output stage into the PCIe engine (hw agent 2026-10-07): hold share ~60 % in EVB mode with ~0 in
    8168              :                 // direct mode means the host is the holder; small in both means it is not
    8169            0 :                 row(12);
    8170            0 :                 o << indent << names[13] << ": " << std::setw(10) << values[13] << " clocks = " << std::setw(8) << std::setprecision(1)
    8171            0 :                   << (values[13] * 4.0e-3) << " us" << (values[13] >= 65536 ? "  (a hold of 262 us or more happened)" : "") << "\n";
    8172            0 :                 o << indent << names[14] << ": " << std::setw(10) << values[14] << " words = " << std::setw(8) << std::setprecision(1)
    8173            0 :                   << (values[14] * 8.0e-6) << " MB";
    8174            0 :                 if (timebase)
    8175            0 :                         o << "  delivered " << std::setprecision(1) << (values[14] * 8.0 / (timebase * 4.0e-9) * 1e-6) << " MB/s";
    8176            0 :                 o << "\n";
    8177              :         }
    8178            0 :         return o.str();
    8179            0 : }
    8180              : }  // namespace
    8181              : 
    8182              : /// Counters since SoftReset.  They wrap at 2^32 (~17 s), so prefer the delta form for a run.
    8183            0 : std::string DTCLib::DTC_Registers::FormatEVBStallCountersText(const std::string& indent)
    8184              : {
    8185            0 :         const auto values = ReadEVBStallCounters();
    8186            0 :         return formatEVBStallRows(std::vector<uint64_t>(values.begin(), values.end()), indent, "since SoftReset");
    8187            0 : }  // end FormatEVBStallCountersText()
    8188              : 
    8189              : /// Difference of two snapshots (32-bit wrap-safe), so the shares cover only the run itself.
    8190              : /// Element 13 (EVBOutputLongestHold) is a since-reset maximum, not a counter: report the
    8191              : /// end-snapshot value directly rather than a meaningless subtraction of two high-water marks.
    8192            0 : std::string DTCLib::DTC_Registers::FormatEVBStallCountersDeltaText(const std::vector<uint32_t>& startValues, const std::vector<uint32_t>& endValues, const std::string& indent)
    8193              : {
    8194              :         static const size_t longestHoldIndex = 13;
    8195            0 :         std::vector<uint64_t> deltas;
    8196            0 :         for (size_t index = 0; index < startValues.size() && index < endValues.size(); ++index)
    8197              :         {
    8198            0 :                 if (index == longestHoldIndex)
    8199            0 :                         deltas.push_back(endValues[index]);
    8200              :                 else
    8201            0 :                         deltas.push_back(static_cast<uint32_t>(endValues[index] - startValues[index]));
    8202              :         }
    8203            0 :         return formatEVBStallRows(deltas, indent, "between the two snapshots");
    8204            0 : }  // end FormatEVBStallCountersDeltaText()
    8205              : 
    8206            0 : std::string DTCLib::DTC_Registers::FormatEVBStallCountersTotalsText(const std::vector<uint64_t>& totals, const std::string& indent)
    8207              : {
    8208            0 :         return formatEVBStallRows(totals, indent, "over the run (summed mid-run snapshots, wrap-safe)");
    8209              : }  // end FormatEVBStallCountersTotalsText()
    8210              : 
    8211              : /// @brief 0x9200 [15:0] - ROC input words
    8212            0 : uint16_t DTCLib::DTC_Registers::ReadEVBROCInputWords(std::optional<uint32_t> val)
    8213              : {
    8214            0 :         return ReadEVBHighLevelCounters0(val) & 0xFFFF;
    8215              : }  // end ReadEVBROCInputWords()
    8216              : 
    8217              : /// @brief 0x9200 [31:16] - Self-transfer words
    8218            0 : uint16_t DTCLib::DTC_Registers::ReadEVBSelfTransferWords(std::optional<uint32_t> val)
    8219              : {
    8220            0 :         return (ReadEVBHighLevelCounters0(val) >> 16) & 0xFFFF;
    8221              : }  // end ReadEVBSelfTransferWords()
    8222              : 
    8223              : /// @brief 0x9204 [15:0] - DDR FIFO write words
    8224            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDDRFIFOWriteWords(std::optional<uint32_t> val)
    8225              : {
    8226            0 :         return ReadEVBHighLevelCounters1(val) & 0xFFFF;
    8227              : }  // end ReadEVBDDRFIFOWriteWords()
    8228              : 
    8229              : /// @brief 0x9204 [31:16] - DDR->TX words
    8230            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDDRToTXWords(std::optional<uint32_t> val)
    8231              : {
    8232            0 :         return (ReadEVBHighLevelCounters1(val) >> 16) & 0xFFFF;
    8233              : }  // end ReadEVBDDRToTXWords()
    8234              : 
    8235              : /// @brief 0x9208 [15:0] - Buffer manager output words
    8236            0 : uint16_t DTCLib::DTC_Registers::ReadEVBBufferManagerOutputWords(std::optional<uint32_t> val)
    8237              : {
    8238            0 :         return ReadEVBHighLevelCounters2(val) & 0xFFFF;
    8239              : }  // end ReadEVBBufferManagerOutputWords()
    8240              : 
    8241              : /// @brief 0x9208 [31:16] - DMA output words
    8242            0 : uint16_t DTCLib::DTC_Registers::ReadEVBDMAOutputWords(std::optional<uint32_t> val)
    8243              : {
    8244            0 :         return (ReadEVBHighLevelCounters2(val) >> 16) & 0xFFFF;
    8245              : }  // end ReadEVBDMAOutputWords()
    8246              : 
    8247              : /// @brief 0x920C [15:0] - GBE RX words
    8248            0 : uint16_t DTCLib::DTC_Registers::ReadEVBGBERXWords(std::optional<uint32_t> val)
    8249              : {
    8250            0 :         return ReadEVBHighLevelCounters3(val) & 0xFFFF;
    8251              : }  // end ReadEVBGBERXWords()
    8252              : 
    8253              : // RX Data Packet Count
    8254            0 : uint32_t DTCLib::DTC_Registers::ReadRXDataPacketCount(DTC_Link_ID const& link, std::optional<uint32_t> val)
    8255              : {
    8256            0 :         return val.has_value() ? *val : ReadRegister_(GetRXDataPacketCountLinkRegister(link));
    8257              : }  // end ReadRXDataPacketCount()
    8258              : 
    8259            0 : DTCLib::RegisterFormatter DTCLib::DTC_Registers::FormatRXDataPacketCountLink(DTC_Link_ID const& link)
    8260              : {
    8261            0 :         auto form = CreateFormatter(GetRXDataPacketCountLinkRegister(link));
    8262            0 :         form.description = "ROC DP RX Count on Link " +
    8263            0 :                                            std::to_string((GetRXDataPacketCountLinkRegister(link) -
    8264            0 :                                                                            GetRXDataPacketCountLinkRegister(DTC_Link_0)) /
    8265            0 :                                                                           4);
    8266            0 :         std::stringstream o;
    8267            0 :         o << std::dec << ReadRXDataHeaderPacketCount(link, form.value);
    8268            0 :         form.vals.push_back(o.str());
    8269            0 :         return form;
    8270            0 : }  // end FormatRXDataPacketCountLink()
    8271              : 
    8272            0 : DTCLib::DTC_Register DTCLib::DTC_Registers::GetRXDataPacketCountLinkRegister(DTC_Link_ID const& link)
    8273              : {
    8274              :         DTC_Register reg;
    8275            0 :         switch (link)
    8276              :         {
    8277            0 :                 case DTC_Link_0:
    8278            0 :                         reg = DTC_Register_RXDataPacketCount_Link0;
    8279            0 :                         break;
    8280            0 :                 case DTC_Link_1:
    8281            0 :                         reg = DTC_Register_RXDataPacketCount_Link1;
    8282            0 :                         break;
    8283            0 :                 case DTC_Link_2:
    8284            0 :                         reg = DTC_Register_RXDataPacketCount_Link2;
    8285            0 :                         break;
    8286            0 :                 case DTC_Link_3:
    8287            0 :                         reg = DTC_Register_RXDataPacketCount_Link3;
    8288            0 :                         break;
    8289            0 :                 case DTC_Link_4:
    8290            0 :                         reg = DTC_Register_RXDataPacketCount_Link4;
    8291            0 :                         break;
    8292            0 :                 case DTC_Link_5:
    8293            0 :                         reg = DTC_Register_RXDataPacketCount_Link5;
    8294            0 :                         break;
    8295            0 :                 default: {
    8296            0 :                         __SS__ << "Illegal link index provided: " << link << __E__;
    8297            0 :                         __SS_THROW__;
    8298            0 :                 }
    8299              :         }
    8300            0 :         return reg;
    8301              : }  // end GetRXDataPacketCountLinkRegister()
    8302              : 
    8303              : // EVB Diagnostic RX Packet FIFO
    8304            0 : uint64_t DTCLib::DTC_Registers::ReadEVBDiagnosticFIFO(std::optional<uint32_t> val)
    8305              : {
    8306            0 :         uint64_t ret = val.has_value() ? *val : ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_High);
    8307            0 :         ret = (ret << 32) + ReadRegister_(DTC_Register_EVBDiagnosticRXPacket_Low);
    8308            0 :         return ret;
    8309              : }
    8310            0 : void DTCLib::DTC_Registers::ClearEVBDiagnosticFIFO()
    8311              : {
    8312            0 :         WriteRegister_(0, DTC_Register_EVBDiagnosticRXPacket_Low);
    8313            0 : }
    8314              : 
    8315              : // Event Mode Lookup Table
    8316              : /// <summary>
    8317              : /// Set all event mode words to the given value
    8318              : /// </summary>
    8319              : /// <param name="data">Value for all event mode words</param>
    8320            0 : void DTCLib::DTC_Registers::SetAllEventModeWords(uint32_t data)
    8321              : {
    8322            0 :         for (uint16_t address = DTC_Register_EventModeLookupTableStart; address <= DTC_Register_EventModeLookupTableEnd;
    8323            0 :                  address += 4)
    8324              :         {
    8325            0 :                 auto retry = 3;
    8326              :                 int errorCode;
    8327              :                 do
    8328              :                 {
    8329            0 :                         errorCode = device_.write_register(address, 100, data);
    8330            0 :                         --retry;
    8331            0 :                 } while (retry > 0 && errorCode != 0);
    8332            0 :                 if (errorCode != 0)
    8333              :                 {
    8334            0 :                         __SS__ << "Error writing register " << address;
    8335            0 :                         __SS_THROW__;
    8336              :                         // throw DTC_IOErrorException(errorCode);
    8337            0 :                 }
    8338              :         }
    8339            0 : }
    8340              : 
    8341              : /// <summary>
    8342              : /// Set a given event mode word
    8343              : /// </summary>
    8344              : /// <param name="which">Word index to write</param>
    8345              : /// <param name="data">Data for word</param>
    8346            0 : void DTCLib::DTC_Registers::SetEventModeWord(uint8_t which, uint32_t data)
    8347              : {
    8348            0 :         uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
    8349            0 :         if (address <= DTC_Register_EventModeLookupTableEnd)
    8350              :         {
    8351            0 :                 auto retry = 3;
    8352              :                 int errorCode;
    8353              :                 do
    8354              :                 {
    8355            0 :                         errorCode = device_.write_register(address, 100, data);
    8356            0 :                         --retry;
    8357            0 :                 } while (retry > 0 && errorCode != 0);
    8358            0 :                 if (errorCode != 0)
    8359              :                 {
    8360            0 :                         __SS__ << "Error writing register " << address;
    8361            0 :                         __SS_THROW__;
    8362              :                         // throw DTC_IOErrorException(errorCode);
    8363            0 :                 }
    8364              :         }
    8365            0 : }
    8366              : 
    8367              : /// <summary>
    8368              : /// Read an event mode word from the Event Mode lookup table
    8369              : /// </summary>
    8370              : /// <param name="which">Word index to read</param>
    8371              : /// <returns>Value of the given event mode word</returns>
    8372            0 : uint32_t DTCLib::DTC_Registers::ReadEventModeWord(uint8_t which)
    8373              : {
    8374            0 :         uint16_t address = DTC_Register_EventModeLookupTableStart + (which * 4);
    8375            0 :         if (address <= DTC_Register_EventModeLookupTableEnd)
    8376              :         {
    8377            0 :                 auto retry = 3;
    8378              :                 int errorCode;
    8379              :                 uint32_t data;
    8380              :                 do
    8381              :                 {
    8382            0 :                         errorCode = device_.read_register(address, 100, &data);
    8383            0 :                         --retry;
    8384            0 :                 } while (retry > 0 && errorCode != 0);
    8385            0 :                 if (errorCode != 0)
    8386              :                 {
    8387            0 :                         __SS__ << "Error writing register " << address;
    8388            0 :                         __SS_THROW__;
    8389              :                         // throw DTC_IOErrorException(errorCode);
    8390            0 :                 }
    8391              : 
    8392            0 :                 return data;
    8393              :         }
    8394            0 :         return 0;
    8395              : }
    8396              : 
    8397              : // Oscillator Programming (DDR and SERDES)
    8398              : /// <summary>
    8399              : /// Set the given oscillator to the given frequency, calculating a new program in the process.
    8400              : /// </summary>
    8401              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    8402              : /// <param name="targetFrequency">New frequency to program, in Hz</param>
    8403              : /// <returns>Whether the oscillator was changed (Will not reset if already set to desired frequency)</returns>
    8404            0 : bool DTCLib::DTC_Registers::SetNewOscillatorFrequency(DTC_OscillatorType oscillator, double targetFrequency)
    8405              : {
    8406            0 :         auto currentFrequency = 0;  // As of 2023 DTCs, can not read frequency back (it was doing nothing, just a scratch register) // ReadCurrentFrequency(oscillator);
    8407            0 :         auto currentProgram = ReadCurrentProgram(oscillator);
    8408            0 :         __COUT__ << "Target Frequency: " << targetFrequency << ", Current Frequency: " << currentFrequency
    8409            0 :                          << ", Current Program: " << std::showbase << std::hex << currentProgram;
    8410              : 
    8411              :         // Check if targetFrequency is essentially the same as the current frequency...
    8412            0 :         if (fabs(currentFrequency - targetFrequency) < targetFrequency * 30 / 1000000)
    8413              :         {
    8414            0 :                 __COUT_INFO__ << "New frequency and old frequency are within 30 ppm of each other, not reprogramming!";
    8415            0 :                 return false;
    8416              :         }
    8417              : 
    8418            0 :         auto newParameters = CalculateFrequencyForProgramming_(targetFrequency, currentFrequency, currentProgram);
    8419            0 :         if (newParameters == 0)
    8420              :         {
    8421            0 :                 __COUT_WARN__ << "New program calculated as 0! Check parameters!";
    8422            0 :                 return false;
    8423              :         }
    8424            0 :         WriteCurrentProgram(newParameters, oscillator);
    8425              :         // WriteCurrentFrequency(targetFrequency, oscillator); //As of 2023 DTCs, can not write frequency back (it was doing nothing, just a scratch register)
    8426            0 :         return true;
    8427              : }
    8428              : 
    8429              : /// <summary>
    8430              : /// Read the current RFREQ and dividers of the given oscillator clock
    8431              : /// </summary>
    8432              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    8433              : /// <returns>64-bit integer contianing current oscillator program</returns>
    8434            0 : uint64_t DTCLib::DTC_Registers::ReadCurrentProgram(DTC_OscillatorType oscillator)
    8435              : {
    8436            0 :         switch (oscillator)
    8437              :         {
    8438            0 :                 case DTC_OscillatorType_SERDES:
    8439            0 :                         return ReadSERDESOscillatorParameters_();
    8440            0 :                 case DTC_OscillatorType_Timing:
    8441            0 :                         return ReadTimingOscillatorParameters_();
    8442              :                 // case DTC_OscillatorType_DDR:
    8443              :                 //      return ReadDDROscillatorParameters_();
    8444            0 :                 default:
    8445            0 :                         __SS__ << "Invalid DTC_OscillatorType to read: " + std::to_string(oscillator);
    8446            0 :                         __SS_THROW__;
    8447              :         }
    8448              :         return 0;
    8449              : }
    8450              : 
    8451              : /// <summary>
    8452              : /// Writes a program for the given oscillator crystal. This function should be paired with a call to
    8453              : /// WriteCurrentFrequency so that subsequent programming attempts work as expected.
    8454              : /// </summary>
    8455              : /// <param name="program">64-bit integer with new RFREQ and dividers</param>
    8456              : /// <param name="oscillator">Oscillator to program, either DDR or SERDES</param>
    8457            0 : void DTCLib::DTC_Registers::WriteCurrentProgram(uint64_t program, DTC_OscillatorType oscillator)
    8458              : {
    8459            0 :         switch (oscillator)
    8460              :         {
    8461            0 :                 case DTC_OscillatorType_SERDES:
    8462            0 :                         SetSERDESOscillatorParameters_(program);
    8463            0 :                         break;
    8464            0 :                 case DTC_OscillatorType_Timing:
    8465            0 :                         SetTimingOscillatorParameters_(program);
    8466            0 :                         break;
    8467              :                 // case DTC_OscillatorType_DDR:
    8468              :                 //      SetDDROscillatorParameters_(program);
    8469              :                 //      break;
    8470            0 :                 default:
    8471            0 :                         __SS__ << "Invalid DTC_OscillatorType to program: " + std::to_string(oscillator);
    8472            0 :                         __SS_THROW__;
    8473              :         }
    8474            0 : }
    8475              : 
    8476              : // Private Functions
    8477            0 : void DTCLib::DTC_Registers::VerifyRegisterWrite_(const CFOandDTC_Register& address, uint32_t readbackValue, uint32_t dataToWrite)
    8478              : {
    8479              :         // verify register readback
    8480              :         if (1)
    8481              :         {
    8482              :                 // uint32_t readbackReturnValue = ReadRegister_(address);
    8483              :                 // uint32_t readbackValue = readbackReturnValue;
    8484              :                 // uint32_t readbackValue = ReadRegister_(address);
    8485              : 
    8486            0 :                 switch (address)  // handle special register checks by masking of DONT-CARE bits, or else check full 32 bits
    8487              :                 {
    8488              :                         //---------- DTC only registers
    8489            0 :                         case DTC_Register_CFOLinkErrorFlags:  // CFO Sample Permanent Offset 2:0
    8490            0 :                                 dataToWrite &= 0x03;
    8491            0 :                                 readbackValue &= 0x03;
    8492            0 :                                 break;
    8493            0 :                         case DTC_Register_CFOMarkerEnables:  // CFO emulator marker enables: 5:0 enables clock marker, 13:8 is event
    8494              :                                                                                                  // marker per ROC link for some reason, now event marker is not returned
    8495              :                                                                                                  // (FIXME?)
    8496            0 :                                 dataToWrite &= 0x03f;
    8497            0 :                                 readbackValue &= 0x03f;
    8498            0 :                                 break;
    8499            0 :                         case DTC_Register_RXCDRUnlockCount_CFOLink:  // write clears 32-bit CDR unlock counter, but can read back errors
    8500              :                                                                                                                  // immediately, so don't check
    8501              :                         case DTC_Register_JitterAttenuatorLossOfLockCount:
    8502              :                         case DTC_Register_JitterAttenuator_SERDES_RXRecoveredClockLOSCount:
    8503              :                         case DTC_Register_JitterAttenuator_SERDES_RXExternalClockLOSCount:
    8504            0 :                                 return;
    8505            0 :                         case DTC_Register_JitterAttenuatorCSR:  // 0x9308 bit-0 is reset, input select bit-5:4, bit-8 is LOL, bit-11:9
    8506              :                                                                                                         // (input LOS).. only check input select bits
    8507            0 :                                 dataToWrite &= (3 << 4);
    8508            0 :                                 readbackValue &= (3 << 4);
    8509            0 :                                 break;
    8510            0 :                         case DTC_Register_CFOEmulation_EventMode2:  // only lower 16-bits are R/W
    8511            0 :                                 dataToWrite &= 0x0000ffff;
    8512            0 :                                 readbackValue &= 0x0000ffff;
    8513            0 :                                 break;
    8514            0 :                         case DTC_Register_DetEmulation_Control1:  // self clearing bit-1, so return immediately
    8515            0 :                                 return;
    8516            0 :                         case DTC_Register_EVBStats:  // addrs for write, data on read
    8517            0 :                                 return;
    8518              : 
    8519            0 :                         default:;  // do direct comparison of each bit
    8520              :                 }              // end readback verification address case handling
    8521              : 
    8522            0 :                 if (readbackValue != dataToWrite)
    8523              :                 {
    8524              :                         try
    8525              :                         {
    8526            0 :                                 __SS__ << "Write check mismatch - "
    8527            0 :                                            << "write value 0x" << std::setw(8) << std::setfill('0') << std::setprecision(8) << std::hex << static_cast<uint32_t>(dataToWrite)
    8528            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
    8529            0 :                                            << std::endl
    8530            0 :                                            << "If you do not understand this error, try checking the DTC firmware version: " << ReadDesignDate() << std::endl;
    8531            0 :                                 __SS_ONLY_THROW__;
    8532            0 :                         }
    8533            0 :                         catch (const std::runtime_error& e)
    8534              :                         {
    8535            0 :                                 std::stringstream ss;
    8536            0 :                                 ss << e.what();
    8537              :                                 ss << "\n\nThe stack trace is as follows:\n"
    8538            0 :                                    << otsStyleStackTrace() << __E__;
    8539            0 :                                 __SS_THROW__;
    8540            0 :                         }
    8541              :                 }
    8542              :                 // return readbackReturnValue;
    8543              :         }  // end verify register readback
    8544              : }  // end VerifyRegisterWrite_()
    8545              : 
    8546            0 : int DTCLib::DTC_Registers::DecodeHighSpeedDivider_(int input)
    8547              : {
    8548            0 :         switch (input)
    8549              :         {
    8550            0 :                 case 0:
    8551            0 :                         return 4;
    8552            0 :                 case 1:
    8553            0 :                         return 5;
    8554            0 :                 case 2:
    8555            0 :                         return 6;
    8556            0 :                 case 3:
    8557            0 :                         return 7;
    8558            0 :                 case 5:
    8559            0 :                         return 9;
    8560            0 :                 case 7:
    8561            0 :                         return 11;
    8562            0 :                 default:
    8563            0 :                         return -1;
    8564              :         }
    8565              : }
    8566              : 
    8567            0 : int DTCLib::DTC_Registers::EncodeHighSpeedDivider_(int input)
    8568              : {
    8569            0 :         switch (input)
    8570              :         {
    8571            0 :                 case 4:
    8572            0 :                         return 0;
    8573            0 :                 case 5:
    8574            0 :                         return 1;
    8575            0 :                 case 6:
    8576            0 :                         return 2;
    8577            0 :                 case 7:
    8578            0 :                         return 3;
    8579            0 :                 case 9:
    8580            0 :                         return 5;
    8581            0 :                 case 11:
    8582            0 :                         return 7;
    8583            0 :                 default:
    8584            0 :                         return -1;
    8585              :         }
    8586              : }
    8587              : 
    8588            0 : int DTCLib::DTC_Registers::EncodeOutputDivider_(int input)
    8589              : {
    8590            0 :         if (input == 1) return 0;
    8591            0 :         int temp = input / 2;
    8592            0 :         return (temp * 2) - 1;
    8593              : }
    8594              : 
    8595            0 : uint64_t DTCLib::DTC_Registers::CalculateFrequencyForProgramming_(double targetFrequency, double currentFrequency,
    8596              :                                                                                                                                   uint64_t currentProgram)
    8597              : {
    8598            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: targetFrequency=" << targetFrequency << ", currentFrequency=" << currentFrequency
    8599            0 :                                                          << ", currentProgram=" << std::showbase << std::hex << static_cast<unsigned long long>(currentProgram);
    8600            0 :         auto currentHighSpeedDivider = DecodeHighSpeedDivider_((currentProgram >> 45) & 0x7);
    8601            0 :         auto currentOutputDivider = DecodeOutputDivider_((currentProgram >> 38) & 0x7F);
    8602            0 :         auto currentRFREQ = DecodeRFREQ_(currentProgram & 0x3FFFFFFFFF);
    8603            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Current HSDIV=" << currentHighSpeedDivider << ", N1=" << currentOutputDivider << ", RFREQ=" << currentRFREQ;
    8604            0 :         const auto minFreq = 4850000000;  // Hz
    8605            0 :         const auto maxFreq = 5670000000;  // Hz
    8606              : 
    8607            0 :         auto fXTAL = currentFrequency * currentHighSpeedDivider * currentOutputDivider / currentRFREQ;
    8608            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: fXTAL=" << fXTAL;
    8609              : 
    8610            0 :         std::vector<int> hsdiv_values = {11, 9, 7, 6, 5, 4};
    8611            0 :         std::vector<std::pair<int, double>> parameter_values;
    8612            0 :         for (auto hsdiv : hsdiv_values)
    8613              :         {
    8614            0 :                 auto minN = minFreq / (targetFrequency * hsdiv);
    8615            0 :                 if (minN > 128) break;
    8616              : 
    8617            0 :                 auto thisN = 2;
    8618            0 :                 if (minN < 1) thisN = 1;
    8619            0 :                 while (thisN < minN)
    8620              :                 {
    8621            0 :                         thisN += 2;
    8622              :                 }
    8623            0 :                 auto fdco_new = hsdiv * thisN * targetFrequency;
    8624            0 :                 TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: Adding solution: HSDIV=" << hsdiv << ", N1=" << thisN << ", fdco_new=" << fdco_new;
    8625            0 :                 parameter_values.push_back(std::make_pair(thisN, fdco_new));
    8626              :         }
    8627              : 
    8628            0 :         auto counter = -1;
    8629            0 :         auto newHighSpeedDivider = 0;
    8630            0 :         auto newOutputDivider = 0;
    8631            0 :         auto newRFREQ = 0.0;
    8632              : 
    8633            0 :         for (auto values : parameter_values)
    8634              :         {
    8635            0 :                 ++counter;
    8636            0 :                 if (values.second > maxFreq) continue;
    8637              : 
    8638            0 :                 newHighSpeedDivider = hsdiv_values[counter];
    8639            0 :                 newOutputDivider = values.first;
    8640            0 :                 newRFREQ = values.second / fXTAL;
    8641            0 :                 break;
    8642              :         }
    8643            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: HSDIV=" << newHighSpeedDivider << ", N1=" << newOutputDivider << ", RFREQ=" << newRFREQ;
    8644              : 
    8645            0 :         if (EncodeHighSpeedDivider_(newHighSpeedDivider) == -1)
    8646              :         {
    8647            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid HSDIV " << newHighSpeedDivider << "!";
    8648            0 :                 return 0;
    8649              :         }
    8650            0 :         if (newOutputDivider > 128 || newOutputDivider < 0)
    8651              :         {
    8652            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid N1 " << newOutputDivider << "!";
    8653            0 :                 return 0;
    8654              :         }
    8655            0 :         if (newRFREQ <= 0)
    8656              :         {
    8657            0 :                 __COUT_ERR__ << "ERROR: CalculateFrequencyForProgramming: Invalid RFREQ " << newRFREQ << "!";
    8658            0 :                 return 0;
    8659              :         }
    8660              : 
    8661            0 :         auto output = (static_cast<uint64_t>(EncodeHighSpeedDivider_(newHighSpeedDivider)) << 45) +
    8662            0 :                                   (static_cast<uint64_t>(EncodeOutputDivider_(newOutputDivider)) << 38) + EncodeRFREQ_(newRFREQ);
    8663            0 :         TLOG(TLVL_CalculateFreq) << __COUT_HDR__ << "CalculateFrequencyForProgramming: New Program: " << std::showbase << std::hex << static_cast<unsigned long long>(output);
    8664            0 :         return output;
    8665            0 : }
    8666              : 
    8667            0 : uint64_t DTCLib::DTC_Registers::ReadSERDESOscillatorParameters_()
    8668              : {
    8669            0 :         uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7)) << 40) +
    8670            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8)) << 32) +
    8671            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9)) << 24) +
    8672            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10)) << 16) +
    8673            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11)) << 8) +
    8674            0 :                                         static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12));
    8675            0 :         return data;
    8676              : }
    8677              : 
    8678            0 : uint64_t DTCLib::DTC_Registers::ReadTimingOscillatorParameters_()
    8679              : {
    8680            0 :         uint64_t data = (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7)) << 40) +
    8681            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8)) << 32) +
    8682            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9)) << 24) +
    8683            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10)) << 16) +
    8684            0 :                                         (static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11)) << 8) +
    8685            0 :                                         static_cast<uint64_t>(ReadSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12));
    8686            0 :         return data;
    8687              : }
    8688              : 
    8689              : // uint64_t DTCLib::DTC_Registers::ReadDDROscillatorParameters_()
    8690              : // {
    8691              : //      uint64_t data = (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7)) << 40) +
    8692              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8)) << 32) +
    8693              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9)) << 24) +
    8694              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10)) << 16) +
    8695              : //                                      (static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11)) << 8) +
    8696              : //                                      static_cast<uint64_t>(ReadDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12));
    8697              : //      return data;
    8698              : // }
    8699              : 
    8700            0 : void DTCLib::DTC_Registers::SetSERDESOscillatorParameters_(uint64_t program)
    8701              : {
    8702            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0x10);
    8703              : 
    8704            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 7, static_cast<uint8_t>(program >> 40));
    8705            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 8, static_cast<uint8_t>(program >> 32));
    8706            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 9, static_cast<uint8_t>(program >> 24));
    8707            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 10, static_cast<uint8_t>(program >> 16));
    8708            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 11, static_cast<uint8_t>(program >> 8));
    8709            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 12, static_cast<uint8_t>(program));
    8710              : 
    8711            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x89, 0);
    8712            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_EVB, 0x87, 0x40);
    8713            0 : }
    8714              : 
    8715            0 : void DTCLib::DTC_Registers::SetTimingOscillatorParameters_(uint64_t program)
    8716              : {
    8717            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0x10);
    8718              : 
    8719            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 7, static_cast<uint8_t>(program >> 40));
    8720            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 8, static_cast<uint8_t>(program >> 32));
    8721            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 9, static_cast<uint8_t>(program >> 24));
    8722            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 10, static_cast<uint8_t>(program >> 16));
    8723            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 11, static_cast<uint8_t>(program >> 8));
    8724            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 12, static_cast<uint8_t>(program));
    8725              : 
    8726            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x89, 0);
    8727            0 :         WriteSERDESIICInterface(DTC_IICSERDESBusAddress_CFO, 0x87, 0x40);
    8728            0 : }
    8729              : 
    8730              : // void DTCLib::DTC_Registers::SetDDROscillatorParameters_(uint64_t program)
    8731              : // {
    8732              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0x10);
    8733              : 
    8734              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 7, static_cast<uint8_t>(program >> 40));
    8735              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 8, static_cast<uint8_t>(program >> 32));
    8736              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 9, static_cast<uint8_t>(program >> 24));
    8737              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 10, static_cast<uint8_t>(program >> 16));
    8738              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 11, static_cast<uint8_t>(program >> 8));
    8739              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 12, static_cast<uint8_t>(program));
    8740              : 
    8741              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x89, 0);
    8742              : //      WriteDDRIICInterface(DTC_IICDDRBusAddress_DDROscillator, 0x87, 0x40);
    8743              : // }
    8744              : 
    8745            0 : bool DTCLib::DTC_Registers::WaitForLinkReady_(DTC_Link_ID const& link, size_t interval, double timeout /*seconds*/)
    8746              : {
    8747            0 :         auto start = std::chrono::steady_clock::now();
    8748            0 :         auto last_print = start;
    8749            0 :         bool ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
    8750              : 
    8751            0 :         while (!ready)
    8752              :         {
    8753            0 :                 usleep(interval);
    8754            0 :                 ready = ReadSERDESPLLLocked(link) && ReadResetRXSERDESDone(link) && ReadResetTXSERDESDone(link) && ReadSERDESRXCDRLock(link);
    8755            0 :                 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - last_print).count() > 5.0)
    8756              :                 {
    8757            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);
    8758            0 :                         last_print = std::chrono::steady_clock::now();
    8759              :                 }
    8760            0 :                 if (std::chrono::duration_cast<std::chrono::duration<double, std::ratio<1>>>(std::chrono::steady_clock::now() - start).count() > timeout)
    8761              :                 {
    8762            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);
    8763            0 :                         return false;
    8764              :                 }
    8765              :         }
    8766            0 :         return true;
    8767              : }
        

Generated by: LCOV version 2.0-1