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 : }
|