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